stds_import.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. """!@package grass.temporal
  2. @brief GRASS Python scripting module (temporal GIS functions)
  3. Temporal GIS export functions to be used in temporal modules
  4. Usage:
  5. @code
  6. import grass.temporal as tgis
  7. input="/tmp/temp_1950_2012.tar.gz"
  8. output="temp_1950_2012"
  9. extrdir="/tmp"
  10. title="My new dataset"
  11. descr="May new shiny dataset"
  12. location=None
  13. link=True
  14. exp=True
  15. overr=False
  16. create=False
  17. tgis.import_stds(input, output, extrdir, title, descr, location,
  18. link, exp, overr, create, "strds")
  19. ...
  20. @endcode
  21. (C) 2008-2011 by the GRASS Development Team
  22. This program is free software under the GNU General Public
  23. License (>=v2). Read the file COPYING that comes with GRASS
  24. for details.
  25. @author Soeren Gebbert
  26. """
  27. import shutil
  28. import os
  29. import os.path
  30. import tarfile
  31. import tempfile
  32. import time
  33. import filecmp
  34. import space_time_datasets_tools
  35. from space_time_datasets_tools import *
  36. proj_file_name = "proj.txt"
  37. init_file_name = "init.txt"
  38. list_file_name = "list.txt"
  39. # This global variable is for unique vector map export,
  40. # since single vector maps may have several layer
  41. # and therefore several attribute tables
  42. imported_maps = {}
  43. ############################################################################
  44. def _import_raster_maps_from_geotiff(maplist, overr, exp, location, link):
  45. impflags = ""
  46. if overr:
  47. impflags += "o"
  48. if exp or location:
  49. impflags += "e"
  50. for row in maplist:
  51. name = row["name"]
  52. filename = str(row["name"]) + ".tif"
  53. if link:
  54. ret = core.run_command("r.external", input=filename,
  55. output=name,
  56. flags=impflags,
  57. overwrite=core.overwrite())
  58. else:
  59. ret = core.run_command("r.in.gdal", input=filename,
  60. output=name,
  61. flags=impflags,
  62. overwrite=core.overwrite())
  63. if ret != 0:
  64. core.fatal(_("Unable to import/link raster map <%s>.") % name)
  65. # Set the color rules if present
  66. filename = str(row["name"]) + ".color"
  67. if os.path.isfile(filename):
  68. ret = core.run_command("r.colors", map=name,
  69. rules=filename,
  70. overwrite=core.overwrite())
  71. if ret != 0:
  72. core.fatal(_("Unable to set the color rules for "
  73. "raster map <%s>.") % name)
  74. ############################################################################
  75. def _import_raster_maps(maplist):
  76. # We need to disable the projection check because of its
  77. # simple implementation
  78. impflags = "o"
  79. for row in maplist:
  80. name = row["name"]
  81. filename = str(row["name"]) + ".pack"
  82. ret = core.run_command("r.unpack", input=filename,
  83. output=name,
  84. flags=impflags,
  85. overwrite=core.overwrite(),
  86. verbose=True)
  87. if ret != 0:
  88. core.fatal(_("Unable to unpack raster map <%s>.") % name)
  89. ############################################################################
  90. def _import_vector_maps_from_gml(maplist, overr, exp, location, link):
  91. impflags = "o"
  92. if exp or location:
  93. impflags += "e"
  94. for row in maplist:
  95. name = row["name"]
  96. filename = str(row["name"]) + ".xml"
  97. ret = core.run_command("v.in.ogr", dsn=filename,
  98. output=name,
  99. flags=impflags,
  100. overwrite=core.overwrite())
  101. if ret != 0:
  102. core.fatal(_("Unable to import vector map <%s>.") % name)
  103. ############################################################################
  104. def _import_vector_maps(maplist):
  105. # We need to disable the projection check because of its
  106. # simple implementation
  107. impflags = "o"
  108. for row in maplist:
  109. # Separate the name from the layer
  110. name = row["name"].split(":")[0]
  111. # Import only unique maps
  112. if name in imported_maps:
  113. continue
  114. filename = name + ".pack"
  115. ret = core.run_command("v.unpack", input=filename,
  116. output=name,
  117. flags=impflags,
  118. overwrite=core.overwrite(),
  119. verbose=True)
  120. if ret != 0:
  121. core.fatal(_("Unable to unpack vector map <%s>.") % name)
  122. imported_maps[name] = name
  123. ############################################################################
  124. def import_stds(
  125. input, output, extrdir, title=None, descr=None, location=None,
  126. link=False, exp=False, overr=False, create=False, stds_type="strds"):
  127. """!Import space time datasets of type raster and vector
  128. @param input: Name of the input archive file
  129. @param output: The name of the output space time dataset
  130. @param extrdir: The extraction directory
  131. @param title: The title of the new created space time dataset
  132. @param description: The description of the new created
  133. space time dataset
  134. @param location: The name of the location that should be created,
  135. maps are imported into this location
  136. @param link: Switch to link raster maps instead importing them
  137. @param exp: Extend location extents based on new dataset
  138. @param overr: Override projection (use location's projection)
  139. @param create: Create the location specified by the "location"
  140. parameter and exit.
  141. Do not import the space time datasets.
  142. @param stds_type: The type of the space time dataset that
  143. should be imported
  144. """
  145. global raise_on_error
  146. old_state = core.raise_on_error
  147. core.set_raise_on_error(True)
  148. # Check if input file and extraction directory exits
  149. if not os.path.exists(input):
  150. core.fatal(_("Space time raster dataset archive <%s> not found")
  151. % input)
  152. if not create and not os.path.exists(extrdir):
  153. core.fatal(_("Extraction directory <%s> not found") % extrdir)
  154. tar = tarfile.open(name=input, mode='r')
  155. # Check for important files
  156. members = tar.getnames()
  157. if init_file_name not in members:
  158. core.fatal(_("Unable to find init file <%s>") % init_file_name)
  159. if list_file_name not in members:
  160. core.fatal(_("Unable to find list file <%s>") % list_file_name)
  161. if proj_file_name not in members:
  162. core.fatal(_("Unable to find projection file <%s>") % proj_file_name)
  163. tar.extractall(path=extrdir)
  164. tar.close()
  165. # Save current working directory path
  166. old_cwd = os.getcwd()
  167. # Switch into the data directory
  168. os.chdir(extrdir)
  169. # Check projection information
  170. if not location:
  171. temp_name = core.tempfile()
  172. temp_file = open(temp_name, "w")
  173. proj_name = os.path.abspath(proj_file_name)
  174. p = core.start_command("g.proj", flags="j", stdout=temp_file)
  175. p.communicate()
  176. temp_file.close()
  177. if not core.compare_key_value_text_files(temp_name, proj_name, sep="="):
  178. if overr:
  179. core.warning(_("Projection information does not match. "
  180. "Proceeding..."))
  181. else:
  182. core.fatal(_("Projection information does not match. Aborting."))
  183. # Create a new location based on the projection information and switch into it
  184. old_env = core.gisenv()
  185. if location:
  186. try:
  187. proj4_string = open(proj_file_name, 'r').read()
  188. core.create_location(dbase=old_env["GISDBASE"],
  189. location=location,
  190. proj4=proj4_string)
  191. # Just create a new location and return
  192. if create:
  193. os.chdir(old_cwd)
  194. return
  195. except Exception as e:
  196. core.fatal(_("Unable to create location %s. Reason: %s")
  197. % (location, str(e)))
  198. # Switch to the new created location
  199. ret = core.run_command("g.mapset", mapset="PERMANENT",
  200. location=location,
  201. gisdbase=old_env["GISDBASE"])
  202. if ret != 0:
  203. core.fatal(_("Unable to switch to location %s") % location)
  204. # create default database connection
  205. ret = core.run_command("t.connect", flags="d")
  206. if ret != 0:
  207. core.fatal(_("Unable to create default temporal database "
  208. "in new location %s") % location)
  209. try:
  210. # Make sure the temporal database exists
  211. space_time_datasets_tools.init()
  212. fs = "|"
  213. maplist = []
  214. mapset = core.gisenv()["MAPSET"]
  215. list_file = open(list_file_name, "r")
  216. # Read the map list from file
  217. line_count = 0
  218. while True:
  219. line = list_file.readline()
  220. if not line:
  221. break
  222. line_list = line.split(fs)
  223. mapname = line_list[0].strip()
  224. mapid = mapname + "@" + mapset
  225. row = {}
  226. row["name"] = mapname
  227. row["id"] = mapid
  228. row["start"] = line_list[1].strip()
  229. row["end"] = line_list[2].strip()
  230. maplist.append(row)
  231. line_count += 1
  232. list_file.close()
  233. # Read the init file
  234. fs = "="
  235. init = {}
  236. init_file = open(init_file_name, "r")
  237. while True:
  238. line = init_file.readline()
  239. if not line:
  240. break
  241. kv = line.split(fs)
  242. init[kv[0]] = kv[1].strip()
  243. init_file.close()
  244. if "temporal_type" not in init or \
  245. "semantic_type" not in init or \
  246. "number_of_maps" not in init:
  247. core.fatal(_("Key words %s, %s or %s not found in init file.") %
  248. ("temporal_type", "semantic_type", "number_of_maps"))
  249. if line_count != int(init["number_of_maps"]):
  250. core.fatal(_("Number of maps mismatch in init and list file."))
  251. _format = "GTiff"
  252. _type = "strds"
  253. if "stds_type" in init:
  254. _type = init["stds_type"]
  255. if "format" in init:
  256. _format = init["format"]
  257. if stds_type != _type:
  258. core.fatal(_("The archive file is of wrong space time dataset type"))
  259. # Check the existence of the files
  260. if _format == "GTiff":
  261. for row in maplist:
  262. filename = str(row["name"]) + ".tif"
  263. if not os.path.exists(filename):
  264. core.fatal(_("Unable to find geotiff raster file "
  265. "<%s> in archive.") % filename)
  266. elif _format == "GML":
  267. for row in maplist:
  268. filename = str(row["name"]) + ".xml"
  269. if not os.path.exists(filename):
  270. core.fatal(_("Unable to find GML vector file "
  271. "<%s> in archive.") % filename)
  272. elif _format == "pack":
  273. for row in maplist:
  274. if _type == "stvds":
  275. filename = str(row["name"].split(":")[0]) + ".pack"
  276. else:
  277. filename = str(row["name"]) + ".pack"
  278. if not os.path.exists(filename):
  279. core.fatal(_("Unable to find GRASS package file "
  280. "<%s> in archive.") % filename)
  281. else:
  282. core.fatal(_("Unsupported input format"))
  283. # Check the space time dataset
  284. id = output + "@" + mapset
  285. sp = dataset_factory(_type, id)
  286. if sp.is_in_db() and core.overwrite() == False:
  287. core.fatal(_("Space time %s dataset <%s> is already in the "
  288. "database. Use the overwrite flag.") % \
  289. (_type, sp.get_id()))
  290. # Import the maps
  291. if _type == "strds":
  292. if _format == "GTiff":
  293. _import_raster_maps_from_geotiff(
  294. maplist, overr, exp, location, link)
  295. if _format == "pack":
  296. _import_raster_maps(maplist)
  297. elif _type == "stvds":
  298. if _format == "GML":
  299. _import_vector_maps_from_gml(
  300. maplist, overr, exp, location, link)
  301. if _format == "pack":
  302. _import_vector_maps(maplist)
  303. # Create the space time dataset
  304. if sp.is_in_db() and core.overwrite() == True:
  305. core.info(_("Overwrite space time %s dataset "
  306. "<%s> and unregister all maps.") % \
  307. (sp.get_new_map_instance(None).get_type(), sp.get_id()))
  308. sp.delete()
  309. sp = sp.get_new_instance(id)
  310. temporal_type = init["temporal_type"]
  311. semantic_type = init["semantic_type"]
  312. core.verbose(_("Create space time %s dataset.") %
  313. sp.get_new_map_instance(None).get_type())
  314. sp.set_initial_values(temporal_type=temporal_type,
  315. semantic_type=semantic_type, title=title,
  316. description=descr)
  317. sp.insert()
  318. # register the maps
  319. fs = "|"
  320. register_maps_in_space_time_dataset(
  321. type=sp.get_new_map_instance(None).get_type(),
  322. name=output, file=list_file_name, start="file",
  323. end="file", dbif=None, fs=fs)
  324. os.chdir(old_cwd)
  325. except:
  326. raise
  327. # Make sure the location is switched back correctly
  328. finally:
  329. if location:
  330. # Switch to the old location
  331. ret = core.run_command("g.mapset", mapset=old_env["MAPSET"],
  332. location=old_env["LOCATION_NAME"],
  333. gisdbase=old_env["GISDBASE"])
  334. core.set_raise_on_error(old_state)