"""!@package grass.temporal @brief GRASS Python scripting module (temporal GIS functions) Temporal GIS export functions to be used in temporal modules Usage: @code import grass.temporal as tgis input="/tmp/temp_1950_2012.tar.gz" output="temp_1950_2012" extrdir="/tmp" title="My new dataset" descr="May new shiny dataset" location=None link=True exp=True overr=False create=False tgis.import_stds(input, output, extrdir, title, descr, location, link, exp, overr, create, "strds") ... @endcode (C) 2008-2011 by the GRASS Development Team This program is free software under the GNU General Public License (>=v2). Read the file COPYING that comes with GRASS for details. @author Soeren Gebbert """ import shutil import os import os.path import tarfile import tempfile import time import filecmp import space_time_datasets_tools from space_time_datasets_tools import * proj_file_name = "proj.txt" init_file_name = "init.txt" list_file_name = "list.txt" # This global variable is for unique vector map export, # since single vector maps may have several layer # and therefore several attribute tables imported_maps = {} ############################################################################ def _import_raster_maps_from_geotiff(maplist, overr, exp, location, link): impflags = "" if overr: impflags += "o" if exp or location: impflags += "e" for row in maplist: name = row["name"] filename = str(row["name"]) + ".tif" if link: ret = core.run_command("r.external", input=filename, output=name, flags=impflags, overwrite=core.overwrite()) else: ret = core.run_command("r.in.gdal", input=filename, output=name, flags=impflags, overwrite=core.overwrite()) if ret != 0: core.fatal(_("Unable to import/link raster map <%s>.") % name) # Set the color rules if present filename = str(row["name"]) + ".color" if os.path.isfile(filename): ret = core.run_command("r.colors", map=name, rules=filename, overwrite=core.overwrite()) if ret != 0: core.fatal(_("Unable to set the color rules for " "raster map <%s>.") % name) ############################################################################ def _import_raster_maps(maplist): # We need to disable the projection check because of its # simple implementation impflags = "o" for row in maplist: name = row["name"] filename = str(row["name"]) + ".pack" ret = core.run_command("r.unpack", input=filename, output=name, flags=impflags, overwrite=core.overwrite(), verbose=True) if ret != 0: core.fatal(_("Unable to unpack raster map <%s>.") % name) ############################################################################ def _import_vector_maps_from_gml(maplist, overr, exp, location, link): impflags = "o" if exp or location: impflags += "e" for row in maplist: name = row["name"] filename = str(row["name"]) + ".xml" ret = core.run_command("v.in.ogr", dsn=filename, output=name, flags=impflags, overwrite=core.overwrite()) if ret != 0: core.fatal(_("Unable to import vector map <%s>.") % name) ############################################################################ def _import_vector_maps(maplist): # We need to disable the projection check because of its # simple implementation impflags = "o" for row in maplist: # Separate the name from the layer name = row["name"].split(":")[0] # Import only unique maps if name in imported_maps: continue filename = name + ".pack" ret = core.run_command("v.unpack", input=filename, output=name, flags=impflags, overwrite=core.overwrite(), verbose=True) if ret != 0: core.fatal(_("Unable to unpack vector map <%s>.") % name) imported_maps[name] = name ############################################################################ def import_stds( input, output, extrdir, title=None, descr=None, location=None, link=False, exp=False, overr=False, create=False, stds_type="strds"): """!Import space time datasets of type raster and vector @param input: Name of the input archive file @param output: The name of the output space time dataset @param extrdir: The extraction directory @param title: The title of the new created space time dataset @param description: The description of the new created space time dataset @param location: The name of the location that should be created, maps are imported into this location @param link: Switch to link raster maps instead importing them @param exp: Extend location extents based on new dataset @param overr: Override projection (use location's projection) @param create: Create the location specified by the "location" parameter and exit. Do not import the space time datasets. @param stds_type: The type of the space time dataset that should be imported """ global raise_on_error old_state = core.raise_on_error core.set_raise_on_error(True) # Check if input file and extraction directory exits if not os.path.exists(input): core.fatal(_("Space time raster dataset archive <%s> not found") % input) if not create and not os.path.exists(extrdir): core.fatal(_("Extraction directory <%s> not found") % extrdir) tar = tarfile.open(name=input, mode='r') # Check for important files members = tar.getnames() if init_file_name not in members: core.fatal(_("Unable to find init file <%s>") % init_file_name) if list_file_name not in members: core.fatal(_("Unable to find list file <%s>") % list_file_name) if proj_file_name not in members: core.fatal(_("Unable to find projection file <%s>") % proj_file_name) tar.extractall(path=extrdir) tar.close() # Save current working directory path old_cwd = os.getcwd() # Switch into the data directory os.chdir(extrdir) # Check projection information if not location: temp_name = core.tempfile() temp_file = open(temp_name, "w") proj_name = os.path.abspath(proj_file_name) p = core.start_command("g.proj", flags="j", stdout=temp_file) p.communicate() temp_file.close() if not core.compare_key_value_text_files(temp_name, proj_name, sep="="): if overr: core.warning(_("Projection information does not match. " "Proceeding...")) else: core.fatal(_("Projection information does not match. Aborting.")) # Create a new location based on the projection information and switch into it old_env = core.gisenv() if location: try: proj4_string = open(proj_file_name, 'r').read() core.create_location(dbase=old_env["GISDBASE"], location=location, proj4=proj4_string) # Just create a new location and return if create: os.chdir(old_cwd) return except Exception as e: core.fatal(_("Unable to create location %s. Reason: %s") % (location, str(e))) # Switch to the new created location ret = core.run_command("g.mapset", mapset="PERMANENT", location=location, gisdbase=old_env["GISDBASE"]) if ret != 0: core.fatal(_("Unable to switch to location %s") % location) # create default database connection ret = core.run_command("t.connect", flags="d") if ret != 0: core.fatal(_("Unable to create default temporal database " "in new location %s") % location) try: # Make sure the temporal database exists space_time_datasets_tools.init() fs = "|" maplist = [] mapset = core.gisenv()["MAPSET"] list_file = open(list_file_name, "r") # Read the map list from file line_count = 0 while True: line = list_file.readline() if not line: break line_list = line.split(fs) mapname = line_list[0].strip() mapid = mapname + "@" + mapset row = {} row["name"] = mapname row["id"] = mapid row["start"] = line_list[1].strip() row["end"] = line_list[2].strip() maplist.append(row) line_count += 1 list_file.close() # Read the init file fs = "=" init = {} init_file = open(init_file_name, "r") while True: line = init_file.readline() if not line: break kv = line.split(fs) init[kv[0]] = kv[1].strip() init_file.close() if "temporal_type" not in init or \ "semantic_type" not in init or \ "number_of_maps" not in init: core.fatal(_("Key words %s, %s or %s not found in init file.") % ("temporal_type", "semantic_type", "number_of_maps")) if line_count != int(init["number_of_maps"]): core.fatal(_("Number of maps mismatch in init and list file.")) _format = "GTiff" _type = "strds" if "stds_type" in init: _type = init["stds_type"] if "format" in init: _format = init["format"] if stds_type != _type: core.fatal(_("The archive file is of wrong space time dataset type")) # Check the existence of the files if _format == "GTiff": for row in maplist: filename = str(row["name"]) + ".tif" if not os.path.exists(filename): core.fatal(_("Unable to find geotiff raster file " "<%s> in archive.") % filename) elif _format == "GML": for row in maplist: filename = str(row["name"]) + ".xml" if not os.path.exists(filename): core.fatal(_("Unable to find GML vector file " "<%s> in archive.") % filename) elif _format == "pack": for row in maplist: if _type == "stvds": filename = str(row["name"].split(":")[0]) + ".pack" else: filename = str(row["name"]) + ".pack" if not os.path.exists(filename): core.fatal(_("Unable to find GRASS package file " "<%s> in archive.") % filename) else: core.fatal(_("Unsupported input format")) # Check the space time dataset id = output + "@" + mapset sp = dataset_factory(_type, id) if sp.is_in_db() and core.overwrite() == False: core.fatal(_("Space time %s dataset <%s> is already in the " "database. Use the overwrite flag.") % \ (_type, sp.get_id())) # Import the maps if _type == "strds": if _format == "GTiff": _import_raster_maps_from_geotiff( maplist, overr, exp, location, link) if _format == "pack": _import_raster_maps(maplist) elif _type == "stvds": if _format == "GML": _import_vector_maps_from_gml( maplist, overr, exp, location, link) if _format == "pack": _import_vector_maps(maplist) # Create the space time dataset if sp.is_in_db() and core.overwrite() == True: core.info(_("Overwrite space time %s dataset " "<%s> and unregister all maps.") % \ (sp.get_new_map_instance(None).get_type(), sp.get_id())) sp.delete() sp = sp.get_new_instance(id) temporal_type = init["temporal_type"] semantic_type = init["semantic_type"] core.verbose(_("Create space time %s dataset.") % sp.get_new_map_instance(None).get_type()) sp.set_initial_values(temporal_type=temporal_type, semantic_type=semantic_type, title=title, description=descr) sp.insert() # register the maps fs = "|" register_maps_in_space_time_dataset( type=sp.get_new_map_instance(None).get_type(), name=output, file=list_file_name, start="file", end="file", dbif=None, fs=fs) os.chdir(old_cwd) except: raise # Make sure the location is switched back correctly finally: if location: # Switch to the old location ret = core.run_command("g.mapset", mapset=old_env["MAPSET"], location=old_env["LOCATION_NAME"], gisdbase=old_env["GISDBASE"]) core.set_raise_on_error(old_state)