GRASS GIS logo

Source code for temporal.c_libraries_interface

# -*- coding: utf-8 -*-
"""
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.

:authors: 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
import grass.lib.temporal as libtgis

###############################################################################


[docs]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 AVAILABLE_MAPSETS = 8 GET_DRIVER_NAME = 9 GET_DATABASE_NAME = 10 G_MAPSET = 11 G_LOCATION = 12 G_GISDBASE = 13 G_FATAL_ERROR = 14 TYPE_RASTER = 0 TYPE_RASTER3D = 1 TYPE_VECTOR = 2 ###############################################################################
def _fatal_error(lock, conn, data): """Calls G_fatal_error()""" libgis.G_fatal_error("Fatal Error in C library server") def _get_mapset(lock, conn, data): """Return the current mapset :param lock: A multiprocessing.Lock instance :param conn: A multiprocessing.Pipe instance used to send True or False :param data: The mapset as list entry 1 [function_id] :returns: Name of the current mapset """ mapset = libgis.G_mapset() conn.send(mapset) def _get_location(lock, conn, data): """Return the current location :param lock: A multiprocessing.Lock instance :param conn: A multiprocessing.Pipe instance used to send True or False :param data: The mapset as list entry 1 [function_id] :returns: Name of the location """ location = libgis.G_location() conn.send(location) def _get_gisdbase(lock, conn, data): """Return the current gisdatabase :param lock: A multiprocessing.Lock instance :param conn: A multiprocessing.Pipe instance used to send True or False :param data: The mapset as list entry 1 [function_id] :returns: Name of the gisdatabase """ gisdbase = libgis.G_gisdbase() conn.send(gisdbase) def _get_driver_name(lock, conn, data): """Return the temporal database driver of a specific mapset :param lock: A multiprocessing.Lock instance :param conn: A multiprocessing.Pipe instance used to send True or False :param data: The mapset as list entry 1 [function_id, mapset] :returns: Name of the driver or None if no temporal database present """ mapset = data[1] if not mapset: mapset = libgis.G_mapset() drstring = libtgis.tgis_get_mapset_driver_name(mapset) conn.send(drstring) ############################################################################### def _get_database_name(lock, conn, data): """Return the temporal database name of a specific mapset :param lock: A multiprocessing.Lock instance :param conn: A multiprocessing.Pipe instance used to send True or False :param data: The mapset as list entry 1 [function_id, mapset] :returns: Name of the database or None if no temporal database present """ mapset = data[1] if not mapset: mapset = libgis.G_mapset() dbstring = libtgis.tgis_get_mapset_database_name(mapset) if dbstring: # We substitute GRASS variables if they are located in the database string # This behavior is in conjunction with db.connect dbstring = dbstring.replace("$GISDBASE", libgis.G_gisdbase()) dbstring = dbstring.replace("$LOCATION_NAME", libgis.G_location()) dbstring = dbstring.replace("$MAPSET", mapset) conn.send(dbstring) ############################################################################### def _available_mapsets(lock, conn, data): """Return all available mapsets the user can access as a list of strings :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] :returns: Names of available mapsets as list of strings """ count = 0 mapset_list = [] try: # Initialize the accessable mapset list, this is bad C design!!! libgis.G_get_mapset_name(0) mapsets = libgis.G_get_available_mapsets() while mapsets[count]: char_list = "" mapset = mapsets[count] permission = libgis.G_mapset_permissions(mapset) in_search_path = libgis.G_is_mapset_in_search_path(mapset) c = 0 while mapset[c] != "\x00": char_list += mapset[c] c += 1 if permission >= 0 and in_search_path == 1: mapset_list.append(char_list) libgis.G_debug(1, "c_library_server._available_mapsets: \n mapset: %s\n"\ " has permission %i\n in search path: %i"%(char_list, permission, in_search_path)) count += 1 # We need to sort the mapset list, but the first one should be # the current mapset current_mapset = libgis.G_mapset() if current_mapset in mapset_list: mapset_list.remove(current_mapset) mapset_list.sort() mapset_list.reverse() mapset_list.append(current_mapset) mapset_list.reverse() except: raise finally: conn.send(mapset_list) 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 :returns: 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 :returns: 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 :returns: 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.value >= 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 = "minutes" start = dt1.minute elif dt1.second > 0: unit = "seconds" start = dt1.second if count.value == 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.minute elif dt2.second > 0: end = dt2.second return (start, end, unit) ############################################################################### def _stop(lock, conn, data): libgis.G_debug(1, "Stop C-interface server") conn.close() lock.release() sys.exit() ############################################################################### # Global server connection server_connection = None server_lock = None
[docs]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]*15 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 functions[RPCDefs.AVAILABLE_MAPSETS] = _available_mapsets functions[RPCDefs.GET_DRIVER_NAME] = _get_driver_name functions[RPCDefs.GET_DATABASE_NAME] = _get_database_name functions[RPCDefs.G_MAPSET] = _get_mapset functions[RPCDefs.G_LOCATION] = _get_location functions[RPCDefs.G_GISDBASE] = _get_gisdbase functions[RPCDefs.G_FATAL_ERROR] = _fatal_error libgis.G_gisinit("c_library_server") libgis.G_debug(1, "Start C-interface server") while True: # Avoid busy waiting conn.poll(4) data = conn.recv() lock.acquire() functions[data[0]](lock, conn, data) lock.release()
[docs]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-block:: python >>> import grass.script as gscript >>> import grass.temporal as tgis >>> gscript.use_temp_region() >>> gscript.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() >>> gscript.run_command("r.mapcalc", expression="test = 1", overwrite=True, quiet=True) 0 >>> gscript.run_command("r3.mapcalc", expression="test = 1", overwrite=True, quiet=True) 0 >>> gscript.run_command("v.random", output="test", n=10, overwrite=True, quiet=True) 0 >>> gscript.run_command("r.timestamp", map="test", date='12 Mar 1995 10:34:40', overwrite=True, quiet=True) 0 >>> gscript.run_command("r3.timestamp", map="test", date='12 Mar 1995 10:34:40', overwrite=True, quiet=True) 0 >>> gscript.run_command("v.timestamp", map="test", date='12 Mar 1995 10:34:40', overwrite=True, quiet=True) 0 # Check mapsets >>> ciface = tgis.CLibrariesInterface() >>> mapsets = ciface.available_mapsets() >>> mapsets[0] == tgis.get_current_mapset() True # 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 10:34:40 1995-03-12 10:34:40 1 >>> ciface.has_raster_timestamp("test", tgis.get_current_mapset()) False >>> ciface.write_raster_timestamp("test", tgis.get_current_mapset(), "13 Jan 1999 14:30:05") 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 10:34:40 1995-03-12 10:34:40 1 >>> ciface.has_raster3d_timestamp("test", tgis.get_current_mapset()) False >>> ciface.write_raster3d_timestamp("test", tgis.get_current_mapset(), "13 Jan 1999 14:30:05") 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 10:34:40 1995-03-12 10:34:40 1 >>> ciface.has_vector_timestamp("test", tgis.get_current_mapset()) False >>> ciface.write_vector_timestamp("test", tgis.get_current_mapset(), "13 Jan 1999 14:30:05") 1 >>> ciface.has_vector_timestamp("test", tgis.get_current_mapset()) True >>> ciface.get_driver_name() 'sqlite' >>> ciface.get_database_name().split("/")[-1] 'sqlite.db' >>> mapset = ciface.get_mapset() >>> location = ciface.get_location() >>> gisdbase = ciface.get_gisdbase() >>> gscript.del_temp_region() """ def __init__(self): self.client_conn = None self.server_conn = None self.queue = None self.server = None self.start_server()
[docs] def start_server(self): self.client_conn, self.server_conn = Pipe(True) 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")
[docs] 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 :returns: 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()
[docs] 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 :returns: 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()
[docs] 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 :returns: 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()
[docs] 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 :returns: 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()
[docs] 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 :returns: 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()
[docs] 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 :returns: 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()
[docs] 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 :returns: 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()
[docs] 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 :returns: 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()
[docs] 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 :returns: 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()
[docs] 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 :returns: 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()
[docs] 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 :returns: 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()
[docs] 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 :returns: 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()
[docs] 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 :returns: 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()
[docs] 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 :returns: 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()
[docs] 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 :returns: 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()
[docs] 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 :returns: 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()
[docs] 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 :returns: 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()
[docs] def write_vector_timestamp(self, name, mapset, timestring, layer=None): """Write a file based vector timestamp 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 :returns: 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()
[docs] def available_mapsets(self): """Return all available mapsets the user can access as a list of strings :returns: Names of available mapsets as list of strings """ self._check_restart_server() self.client_conn.send([RPCDefs.AVAILABLE_MAPSETS, ]) return self.client_conn.recv()
[docs] def get_driver_name(self, mapset=None): """Return the temporal database driver of a specific mapset :param mapset: Name of the mapset :returns: Name of the driver or None if no temporal database present """ self._check_restart_server() self.client_conn.send([RPCDefs.GET_DRIVER_NAME, mapset]) return self.client_conn.recv()
[docs] def get_database_name(self, mapset=None): """Return the temporal database name of a specific mapset :param mapset: Name of the mapset :returns: Name of the database or None if no temporal database present """ self._check_restart_server() self.client_conn.send([RPCDefs.GET_DATABASE_NAME, mapset]) return self.client_conn.recv()
[docs] def get_mapset(self): """Return the current mapset :returns: Name of the current mapset """ self._check_restart_server() self.client_conn.send([RPCDefs.G_MAPSET, ]) return self.client_conn.recv()
[docs] def get_location(self): """Return the location :returns: Name of the location """ self._check_restart_server() self.client_conn.send([RPCDefs.G_LOCATION, ]) return self.client_conn.recv()
[docs] def get_gisdbase(self): """Return the gisdatabase :returns: Name of the gisdatabase """ self._check_restart_server() self.client_conn.send([RPCDefs.G_GISDBASE, ]) return self.client_conn.recv()
[docs] def fatal_error(self, mapset=None): """Return the temporal database name of a specific mapset :param mapset: Name of the mapset :returns: Name of the database or None if no temporal database present """ self._check_restart_server() self.client_conn.send([RPCDefs.G_FATAL_ERROR])
[docs] def stop(self): """Stop the messenger server and close the pipe This method should be called at exit using the package atexit """ 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()

Help Index | Topics Index | Keywords Index | Full Index

© 2003-2018 GRASS Development Team, GRASS GIS 7.0.7svn Reference Manual