stds_import.py 14 KB

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