r.unpack.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. #!/usr/bin/env python3
  2. ############################################################################
  3. #
  4. # MODULE: r.unpack
  5. # AUTHOR(S): Hamish Bowman, Otago University, New Zealand
  6. # Converted to Python by Martin Landa <landa.martin gmail.com>
  7. # PURPOSE: Unpack up a raster map packed with r.pack
  8. # COPYRIGHT: (C) 2010-2017 by the GRASS Development Team
  9. #
  10. # This program is free software under the GNU General
  11. # Public License (>=v2). Read the file COPYING that
  12. # comes with GRASS for details.
  13. #
  14. #############################################################################
  15. # %module
  16. # % description: Imports a GRASS GIS specific raster archive file (packed with r.pack) as a raster map
  17. # % keyword: raster
  18. # % keyword: import
  19. # % keyword: copying
  20. # %end
  21. # %option G_OPT_F_BIN_INPUT
  22. # % description: Name of input pack file
  23. # % key_desc: name.pack
  24. # %end
  25. # %option G_OPT_R_OUTPUT
  26. # % description: Name for output raster map (default: taken from input file internals)
  27. # % required: no
  28. # % guisection: Output settings
  29. # %end
  30. # %flag
  31. # % key: o
  32. # % label: Override projection check (use current location's projection)
  33. # % description: Assume that the dataset has same projection as the current location
  34. # % guisection: Output settings
  35. # %end
  36. # %flag
  37. # % key: p
  38. # % label: Print projection information of input pack file and exit
  39. # % guisection: Print
  40. # %end
  41. import os
  42. import sys
  43. import shutil
  44. import tarfile
  45. import atexit
  46. from grass.script.utils import diff_files, try_rmdir
  47. from grass.script import core as grass
  48. def cleanup():
  49. try_rmdir(tmp_dir)
  50. def main():
  51. infile = options["input"]
  52. global tmp_dir
  53. tmp_dir = grass.tempdir()
  54. grass.debug("tmp_dir = {tmpdir}".format(tmpdir=tmp_dir))
  55. if not os.path.exists(infile):
  56. grass.fatal(_("File {name} not found.".format(name=infile)))
  57. gisenv = grass.gisenv()
  58. mset_dir = os.path.join(
  59. gisenv["GISDBASE"], gisenv["LOCATION_NAME"], gisenv["MAPSET"]
  60. )
  61. input_base = os.path.basename(infile)
  62. shutil.copyfile(infile, os.path.join(tmp_dir, input_base))
  63. os.chdir(tmp_dir)
  64. tar = tarfile.TarFile.open(name=input_base, mode="r")
  65. try:
  66. data_names = [
  67. tarinfo.name for tarinfo in tar.getmembers() if "/" not in tarinfo.name
  68. ]
  69. except:
  70. grass.fatal(_("Pack file unreadable"))
  71. if flags["p"]:
  72. # print proj info and exit
  73. try:
  74. for fname in ["PROJ_INFO", "PROJ_UNITS"]:
  75. f = tar.extractfile("{}/{}".format(data_names[0], fname))
  76. sys.stdout.write(f.read().decode())
  77. except KeyError:
  78. grass.fatal(_("Pack file unreadable: file '{}' missing".format(fname)))
  79. tar.close()
  80. return 0
  81. if options["output"]:
  82. map_name = options["output"]
  83. else:
  84. map_name = data_names[0].split("@")[0]
  85. gfile = grass.find_file(name=map_name, element="cell", mapset=".")
  86. if gfile["file"]:
  87. if os.environ.get("GRASS_OVERWRITE", "0") != "1":
  88. grass.fatal(_("Raster map <{name}> already exists".format(name=map_name)))
  89. else:
  90. grass.warning(
  91. _(
  92. "Raster map <{name}> already exists and will be overwritten".format(
  93. name=map_name
  94. )
  95. )
  96. )
  97. # extract data
  98. tar.extractall()
  99. tar.close()
  100. os.chdir(data_names[0])
  101. if os.path.exists("cell"):
  102. pass
  103. elif os.path.exists("coor"):
  104. grass.fatal(
  105. _(
  106. "This GRASS GIS pack file contains vector data. Use "
  107. "v.unpack to unpack <{name}>".format(name=map_name)
  108. )
  109. )
  110. else:
  111. grass.fatal(_("Pack file unreadable"))
  112. # check projection compatibility in a rather crappy way
  113. if flags["o"]:
  114. grass.warning(
  115. _("Overriding projection check (using current location's projection).")
  116. )
  117. else:
  118. diff_result_1 = diff_result_2 = None
  119. proj_info_file_1 = "PROJ_INFO"
  120. proj_info_file_2 = os.path.join(mset_dir, "..", "PERMANENT", "PROJ_INFO")
  121. skip_projection_check = False
  122. if not os.path.exists(proj_info_file_1):
  123. if os.path.exists(proj_info_file_2):
  124. grass.fatal(
  125. _(
  126. "PROJ_INFO file is missing, unpack raster map in XY (unprojected) location."
  127. )
  128. )
  129. skip_projection_check = True # XY location
  130. if not skip_projection_check:
  131. if not grass.compare_key_value_text_files(
  132. filename_a=proj_info_file_1, filename_b=proj_info_file_2, proj=True
  133. ):
  134. diff_result_1 = diff_files(proj_info_file_1, proj_info_file_2)
  135. proj_units_file_1 = "PROJ_UNITS"
  136. proj_units_file_2 = os.path.join(mset_dir, "..", "PERMANENT", "PROJ_UNITS")
  137. if not grass.compare_key_value_text_files(
  138. filename_a=proj_units_file_1, filename_b=proj_units_file_2, units=True
  139. ):
  140. diff_result_2 = diff_files(proj_units_file_1, proj_units_file_2)
  141. if diff_result_1 or diff_result_2:
  142. if diff_result_1:
  143. grass.warning(
  144. _(
  145. "Difference between PROJ_INFO file of packed map "
  146. "and of current location:\n{diff}"
  147. ).format(diff="".join(diff_result_1))
  148. )
  149. if diff_result_2:
  150. grass.warning(
  151. _(
  152. "Difference between PROJ_UNITS file of packed map "
  153. "and of current location:\n{diff}"
  154. ).format(diff="".join(diff_result_2))
  155. )
  156. grass.fatal(
  157. _(
  158. "Projection of dataset does not appear to match current location."
  159. " In case of no significant differences in the projection definitions,"
  160. " use the -o flag to ignore them and use"
  161. " current location definition."
  162. )
  163. )
  164. maps = []
  165. vrt_file = None
  166. for index, data in enumerate(data_names):
  167. if index > 0:
  168. map_name = data
  169. for element in ["cats", "cell", "cellhd", "cell_misc", "colr", "fcell", "hist"]:
  170. src_path = os.path.join(tmp_dir, data, element)
  171. if not os.path.exists(src_path):
  172. continue
  173. path = os.path.join(mset_dir, element)
  174. if not os.path.exists(path):
  175. os.mkdir(path)
  176. if element == "cell_misc":
  177. if index > 0:
  178. maps.append(
  179. "{map_name}@{mapset}".format(
  180. map_name=map_name,
  181. mapset=gisenv["MAPSET"],
  182. ),
  183. )
  184. path = os.path.join(
  185. mset_dir,
  186. element,
  187. map_name,
  188. )
  189. if index == 0:
  190. vrt_file = os.path.join(path, "vrt")
  191. if os.path.exists(path):
  192. shutil.rmtree(path)
  193. shutil.copytree(src_path, path)
  194. else:
  195. shutil.copyfile(
  196. src_path,
  197. os.path.join(mset_dir, element, map_name),
  198. )
  199. # Update vrt file
  200. if maps:
  201. if vrt_file and os.path.exists(vrt_file):
  202. files = "\n".join(maps)
  203. with open(vrt_file, "w") as f:
  204. f.write(files)
  205. grass.message(_("Raster map <{name}> unpacked".format(name=map_name)))
  206. if __name__ == "__main__":
  207. options, flags = grass.parser()
  208. atexit.register(cleanup)
  209. sys.exit(main())