stds_import.py 17 KB

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