123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- #!/usr/bin/env python3
- ############################################################################
- #
- # MODULE: r.unpack
- # AUTHOR(S): Hamish Bowman, Otago University, New Zealand
- # Converted to Python by Martin Landa <landa.martin gmail.com>
- # PURPOSE: Unpack up a raster map packed with r.pack
- # COPYRIGHT: (C) 2010-2017 by the GRASS Development Team
- #
- # This program is free software under the GNU General
- # Public License (>=v2). Read the file COPYING that
- # comes with GRASS for details.
- #
- #############################################################################
- # %module
- # % description: Imports a GRASS GIS specific raster archive file (packed with r.pack) as a raster map
- # % keyword: raster
- # % keyword: import
- # % keyword: copying
- # %end
- # %option G_OPT_F_BIN_INPUT
- # % description: Name of input pack file
- # % key_desc: name.pack
- # %end
- # %option G_OPT_R_OUTPUT
- # % description: Name for output raster map (default: taken from input file internals)
- # % required: no
- # % guisection: Output settings
- # %end
- # %flag
- # % key: o
- # % label: Override projection check (use current location's projection)
- # % description: Assume that the dataset has same projection as the current location
- # % guisection: Output settings
- # %end
- # %flag
- # % key: p
- # % label: Print projection information of input pack file and exit
- # % guisection: Print
- # %end
- import os
- import sys
- import shutil
- import tarfile
- import atexit
- from grass.script.utils import diff_files, try_rmdir
- from grass.script import core as grass
- def cleanup():
- try_rmdir(tmp_dir)
- def main():
- infile = options["input"]
- global tmp_dir
- tmp_dir = grass.tempdir()
- grass.debug("tmp_dir = {tmpdir}".format(tmpdir=tmp_dir))
- if not os.path.exists(infile):
- grass.fatal(_("File {name} not found.".format(name=infile)))
- gisenv = grass.gisenv()
- mset_dir = os.path.join(
- gisenv["GISDBASE"], gisenv["LOCATION_NAME"], gisenv["MAPSET"]
- )
- input_base = os.path.basename(infile)
- shutil.copyfile(infile, os.path.join(tmp_dir, input_base))
- os.chdir(tmp_dir)
- tar = tarfile.TarFile.open(name=input_base, mode="r")
- try:
- data_names = [
- tarinfo.name for tarinfo in tar.getmembers() if "/" not in tarinfo.name
- ]
- except:
- grass.fatal(_("Pack file unreadable"))
- if flags["p"]:
- # print proj info and exit
- try:
- for fname in ["PROJ_INFO", "PROJ_UNITS"]:
- f = tar.extractfile("{}/{}".format(data_names[0], fname))
- sys.stdout.write(f.read().decode())
- except KeyError:
- grass.fatal(_("Pack file unreadable: file '{}' missing".format(fname)))
- tar.close()
- return 0
- if options["output"]:
- map_name = options["output"]
- else:
- map_name = data_names[0].split("@")[0]
- gfile = grass.find_file(name=map_name, element="cell", mapset=".")
- if gfile["file"]:
- if os.environ.get("GRASS_OVERWRITE", "0") != "1":
- grass.fatal(_("Raster map <{name}> already exists".format(name=map_name)))
- else:
- grass.warning(
- _(
- "Raster map <{name}> already exists and will be overwritten".format(
- name=map_name
- )
- )
- )
- # extract data
- tar.extractall()
- tar.close()
- os.chdir(data_names[0])
- if os.path.exists("cell"):
- pass
- elif os.path.exists("coor"):
- grass.fatal(
- _(
- "This GRASS GIS pack file contains vector data. Use "
- "v.unpack to unpack <{name}>".format(name=map_name)
- )
- )
- else:
- grass.fatal(_("Pack file unreadable"))
- # check projection compatibility in a rather crappy way
- if flags["o"]:
- grass.warning(
- _("Overriding projection check (using current location's projection).")
- )
- else:
- diff_result_1 = diff_result_2 = None
- proj_info_file_1 = "PROJ_INFO"
- proj_info_file_2 = os.path.join(mset_dir, "..", "PERMANENT", "PROJ_INFO")
- skip_projection_check = False
- if not os.path.exists(proj_info_file_1):
- if os.path.exists(proj_info_file_2):
- grass.fatal(
- _(
- "PROJ_INFO file is missing, unpack raster map in XY (unprojected) location."
- )
- )
- skip_projection_check = True # XY location
- if not skip_projection_check:
- if not grass.compare_key_value_text_files(
- filename_a=proj_info_file_1, filename_b=proj_info_file_2, proj=True
- ):
- diff_result_1 = diff_files(proj_info_file_1, proj_info_file_2)
- proj_units_file_1 = "PROJ_UNITS"
- proj_units_file_2 = os.path.join(mset_dir, "..", "PERMANENT", "PROJ_UNITS")
- if not grass.compare_key_value_text_files(
- filename_a=proj_units_file_1, filename_b=proj_units_file_2, units=True
- ):
- diff_result_2 = diff_files(proj_units_file_1, proj_units_file_2)
- if diff_result_1 or diff_result_2:
- if diff_result_1:
- grass.warning(
- _(
- "Difference between PROJ_INFO file of packed map "
- "and of current location:\n{diff}"
- ).format(diff="".join(diff_result_1))
- )
- if diff_result_2:
- grass.warning(
- _(
- "Difference between PROJ_UNITS file of packed map "
- "and of current location:\n{diff}"
- ).format(diff="".join(diff_result_2))
- )
- grass.fatal(
- _(
- "Projection of dataset does not appear to match current location."
- " In case of no significant differences in the projection definitions,"
- " use the -o flag to ignore them and use"
- " current location definition."
- )
- )
- maps = []
- vrt_file = None
- for index, data in enumerate(data_names):
- if index > 0:
- map_name = data
- for element in ["cats", "cell", "cellhd", "cell_misc", "colr", "fcell", "hist"]:
- src_path = os.path.join(tmp_dir, data, element)
- if not os.path.exists(src_path):
- continue
- path = os.path.join(mset_dir, element)
- if not os.path.exists(path):
- os.mkdir(path)
- if element == "cell_misc":
- if index > 0:
- maps.append(
- "{map_name}@{mapset}".format(
- map_name=map_name,
- mapset=gisenv["MAPSET"],
- ),
- )
- path = os.path.join(
- mset_dir,
- element,
- map_name,
- )
- if index == 0:
- vrt_file = os.path.join(path, "vrt")
- if os.path.exists(path):
- shutil.rmtree(path)
- shutil.copytree(src_path, path)
- else:
- shutil.copyfile(
- src_path,
- os.path.join(mset_dir, element, map_name),
- )
- # Update vrt file
- if maps:
- if vrt_file and os.path.exists(vrt_file):
- files = "\n".join(maps)
- with open(vrt_file, "w") as f:
- f.write(files)
- grass.message(_("Raster map <{name}> unpacked".format(name=map_name)))
- if __name__ == "__main__":
- options, flags = grass.parser()
- atexit.register(cleanup)
- sys.exit(main())
|