stds_import.py 14 KB

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