r.unpack.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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 re
  43. import sys
  44. import shutil
  45. import tarfile
  46. import atexit
  47. from grass.script.utils import diff_files, try_rmdir
  48. from grass.script import core as grass
  49. def cleanup():
  50. try_rmdir(tmp_dir)
  51. def main():
  52. infile = options['input']
  53. global tmp_dir
  54. tmp_dir = grass.tempdir()
  55. grass.debug('tmp_dir = {tmpdir}'.format(tmpdir=tmp_dir))
  56. if not os.path.exists(infile):
  57. grass.fatal(_('File {name} not found.'.format(name=infile)))
  58. gisenv = grass.gisenv()
  59. mset_dir = os.path.join(gisenv['GISDBASE'],
  60. gisenv['LOCATION_NAME'],
  61. gisenv['MAPSET'])
  62. input_base = os.path.basename(infile)
  63. shutil.copyfile(infile, os.path.join(tmp_dir, input_base))
  64. os.chdir(tmp_dir)
  65. tar = tarfile.TarFile.open(name=input_base, mode='r')
  66. try:
  67. data_names = [
  68. tarinfo.name for tarinfo in tar.getmembers()
  69. if '/' not in tarinfo.name
  70. ]
  71. except:
  72. grass.fatal(_("Pack file unreadable"))
  73. if flags['p']:
  74. # print proj info and exit
  75. try:
  76. for fname in ['PROJ_INFO', 'PROJ_UNITS']:
  77. f = tar.extractfile('{}/{}'.format(data_names[0], fname))
  78. sys.stdout.write(f.read().decode())
  79. except KeyError:
  80. grass.fatal(_("Pack file unreadable: file '{}' missing".format(fname)))
  81. tar.close()
  82. return 0
  83. if options['output']:
  84. map_name = options['output']
  85. else:
  86. map_name = data_names[0].split('@')[0]
  87. gfile = grass.find_file(name=map_name, element='cell', mapset='.')
  88. if gfile['file']:
  89. if os.environ.get('GRASS_OVERWRITE', '0') != '1':
  90. grass.fatal(_('Raster map <{name}> already exists'.format(name=map_name)))
  91. else:
  92. grass.warning(
  93. _('Raster map <{name}> already exists and will be overwritten'.format(name=map_name)))
  94. # extract data
  95. tar.extractall()
  96. tar.close()
  97. os.chdir(data_names[0])
  98. if os.path.exists('cell'):
  99. pass
  100. elif os.path.exists('coor'):
  101. grass.fatal(_('This GRASS GIS pack file contains vector data. Use '
  102. 'v.unpack to unpack <{name}>'.format(name=map_name)))
  103. else:
  104. grass.fatal(_("Pack file unreadable"))
  105. # check projection compatibility in a rather crappy way
  106. if flags['o']:
  107. grass.warning(_("Overriding projection check (using current location's projection)."))
  108. else:
  109. diff_result_1 = diff_result_2 = None
  110. proj_info_file_1 = 'PROJ_INFO'
  111. proj_info_file_2 = os.path.join(mset_dir, '..', 'PERMANENT', 'PROJ_INFO')
  112. skip_projection_check = False
  113. if not os.path.exists(proj_info_file_1):
  114. if os.path.exists(proj_info_file_2):
  115. grass.fatal(
  116. _("PROJ_INFO file is missing, unpack raster map in XY (unprojected) location."))
  117. skip_projection_check = True # XY location
  118. if not skip_projection_check:
  119. if not grass.compare_key_value_text_files(filename_a=proj_info_file_1,
  120. filename_b=proj_info_file_2,
  121. proj=True):
  122. diff_result_1 = diff_files(proj_info_file_1, proj_info_file_2)
  123. proj_units_file_1 = 'PROJ_UNITS'
  124. proj_units_file_2 = os.path.join(mset_dir, '..', 'PERMANENT', 'PROJ_UNITS')
  125. if not grass.compare_key_value_text_files(filename_a=proj_units_file_1,
  126. filename_b=proj_units_file_2,
  127. units=True):
  128. diff_result_2 = diff_files(proj_units_file_1, proj_units_file_2)
  129. if diff_result_1 or diff_result_2:
  130. if diff_result_1:
  131. grass.warning(_("Difference between PROJ_INFO file of packed map "
  132. "and of current location:\n{diff}").format(diff=''.join(diff_result_1)))
  133. if diff_result_2:
  134. grass.warning(_("Difference between PROJ_UNITS file of packed map "
  135. "and of current location:\n{diff}").format(diff=''.join(diff_result_2)))
  136. grass.fatal(_("Projection of dataset does not appear to match current location."
  137. " In case of no significant differences in the projection definitions,"
  138. " use the -o flag to ignore them and use"
  139. " current location definition."))
  140. maps = []
  141. vrt_file = None
  142. for index, data in enumerate(data_names):
  143. if index > 0:
  144. map_name = data
  145. for element in [
  146. 'cats', 'cell', 'cellhd', 'cell_misc', 'colr', 'fcell',
  147. 'hist'
  148. ]:
  149. src_path = os.path.join(tmp_dir, data, element)
  150. if not os.path.exists(src_path):
  151. continue
  152. path = os.path.join(mset_dir, element)
  153. if not os.path.exists(path):
  154. os.mkdir(path)
  155. if element == 'cell_misc':
  156. if index > 0:
  157. maps.append(
  158. "{map_name}@{mapset}".format(
  159. map_name=map_name, mapset=gisenv['MAPSET'],
  160. ),
  161. )
  162. path = os.path.join(
  163. mset_dir, element, map_name,
  164. )
  165. if index == 0:
  166. vrt_file = os.path.join(path, 'vrt')
  167. if os.path.exists(path):
  168. shutil.rmtree(path)
  169. shutil.copytree(src_path, path)
  170. else:
  171. shutil.copyfile(
  172. src_path, os.path.join(mset_dir, element, map_name),
  173. )
  174. # Update vrt file
  175. if maps:
  176. if vrt_file and os.path.exists(vrt_file):
  177. files = '\n'.join(maps)
  178. with open(vrt_file, 'w') as f:
  179. f.write(files)
  180. grass.message(_('Raster map <{name}> unpacked'.format(name=map_name)))
  181. if __name__ == "__main__":
  182. options, flags = grass.parser()
  183. atexit.register(cleanup)
  184. sys.exit(main())