123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- #!/usr/bin/env python3
- #
- ############################################################################
- #
- # MODULE: r_in_aster.py
- # AUTHOR(S): Markus Neteler 11/2003 neteler AT itc it
- # Hamish Bowman
- # Glynn Clements
- # Luca Delucchi
- # PURPOSE: import of SRTM hgt files into GRASS
- #
- # COPYRIGHT: (C) 2004, 2006 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.
- #
- # Dec 2004: merged with srtm_generate_hdr.sh (M. Neteler)
- # corrections and refinement (W. Kyngesburye)
- # Aug 2004: modified to accept files from other directories
- # (by H. Bowman)
- # June 2005: added flag to read in US 1-arcsec tiles (H. Bowman)
- # April 2006: links updated from ftp://e0dps01u.ecs.nasa.gov/srtm/
- # to current links below
- # October 2008: Converted to Python by Glynn Clements
- # March 2018: Added capabilities to import SRTM SWBD
- # Removed unzip dependencies, now it use Python zipfile library
- # by Luca Delucchi
- #########################
- # Derived from:
- # ftp://e0srp01u.ecs.nasa.gov/srtm/version1/Documentation/Notes_for_ARCInfo_users.txt
- # (note: document was updated silently end of 2003)
- #
- # ftp://e0srp01u.ecs.nasa.gov/srtm/version1/Documentation/SRTM_Topo.txt
- # "3.0 Data Formats
- # [...]
- # To be more exact, these coordinates refer to the geometric center of
- # the lower left pixel, which in the case of SRTM-1 data will be about
- # 30 meters in extent."
- #
- # - SRTM 90 Tiles are 1 degree by 1 degree
- # - SRTM filename coordinates are said to be the *center* of the LL pixel.
- # N51E10 -> lower left cell center
- #
- # - BIL uses *center* of the UL (!) pixel:
- # http://downloads.esri.com/support/whitepapers/other_/eximgav.pdf
- #
- # - GDAL uses *corners* of pixels for its coordinates.
- #
- # NOTE: Even, if small difference: SRTM is referenced to EGM96, not WGS84 ellps
- # http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm96/intpt.html
- #
- #########################
- # %Module
- # % description: Imports SRTM HGT files into raster map.
- # % keyword: raster
- # % keyword: import
- # % keyword: SRTM
- # %End
- # %option G_OPT_F_INPUT
- # % description: Name of SRTM input tile (file without .hgt.zip extension)
- # %end
- # %option G_OPT_R_OUTPUT
- # % description: Name for output raster map (default: input tile)
- # % required : no
- # %end
- # %flag
- # % key: 1
- # % description: Input is a 1-arcsec tile (default: 3-arcsec)
- # %end
- import os
- import shutil
- import atexit
- import grass.script as grass
- import zipfile as zfile
- tmpl1sec = """BYTEORDER M
- LAYOUT BIL
- NROWS 3601
- NCOLS 3601
- NBANDS 1
- NBITS 16
- BANDROWBYTES 7202
- TOTALROWBYTES 7202
- BANDGAPBYTES 0
- PIXELTYPE SIGNEDINT
- NODATA -32768
- ULXMAP %s
- ULYMAP %s
- XDIM 0.000277777777777778
- YDIM 0.000277777777777778
- """
- swbd1sec = """BYTEORDER M
- LAYOUT BIL
- NROWS 3601
- NCOLS 3601
- NBANDS 1
- NBITS 8
- BANDROWBYTES 7202
- TOTALROWBYTES 7202
- BANDGAPBYTES 0
- PIXELTYPE SIGNEDINT
- NODATA -32768
- ULXMAP %s
- ULYMAP %s
- XDIM 0.000277777777777778
- YDIM 0.000277777777777778
- """
- tmpl3sec = """BYTEORDER M
- LAYOUT BIL
- NROWS 1201
- NCOLS 1201
- NBANDS 1
- NBITS 16
- BANDROWBYTES 2402
- TOTALROWBYTES 2402
- BANDGAPBYTES 0
- PIXELTYPE SIGNEDINT
- NODATA -32768
- ULXMAP %s
- ULYMAP %s
- XDIM 0.000833333333333
- YDIM 0.000833333333333
- """
- proj = "".join(
- [
- "GEOGCS[",
- '"wgs84",',
- 'DATUM["WGS_1984",SPHEROID["wgs84",6378137,298.257223563],TOWGS84[0.000000,0.000000,0.000000]],',
- 'PRIMEM["Greenwich",0],',
- 'UNIT["degree",0.0174532925199433]',
- "]",
- ]
- )
- def cleanup():
- if not in_temp:
- return
- for ext in [".bil", ".hdr", ".prj", ".hgt.zip"]:
- grass.try_remove(tile + ext)
- os.chdir("..")
- grass.try_rmdir(tmpdir)
- def main():
- global tile, tmpdir, in_temp
- in_temp = False
- # to support SRTM water body
- swbd = False
- input = options["input"]
- output = options["output"]
- one = flags["1"]
- # are we in LatLong location?
- s = grass.read_command("g.proj", flags="j")
- kv = grass.parse_key_val(s)
- if "+proj" not in kv.keys() or kv["+proj"] != "longlat":
- grass.fatal(_("This module only operates in LatLong locations"))
- # use these from now on:
- infile = input
- while infile[-4:].lower() in [".hgt", ".zip", ".raw"]:
- infile = infile[:-4]
- (fdir, tile) = os.path.split(infile)
- if not output:
- tileout = tile
- else:
- tileout = output
- if ".hgt" in input:
- suff = ".hgt"
- else:
- suff = ".raw"
- swbd = True
- zipfile = "{im}{su}.zip".format(im=infile, su=suff)
- hgtfile = "{im}{su}".format(im=infile, su=suff)
- if os.path.isfile(zipfile):
- # really a ZIP file?
- if not zfile.is_zipfile(zipfile):
- grass.fatal(_("'%s' does not appear to be a valid zip file.") % zipfile)
- is_zip = True
- elif os.path.isfile(hgtfile):
- # try and see if it's already unzipped
- is_zip = False
- else:
- grass.fatal(_("File '%s' or '%s' not found") % (zipfile, hgtfile))
- # make a temporary directory
- tmpdir = grass.tempfile()
- grass.try_remove(tmpdir)
- os.mkdir(tmpdir)
- if is_zip:
- shutil.copyfile(
- zipfile, os.path.join(tmpdir, "{im}{su}.zip".format(im=tile, su=suff))
- )
- else:
- shutil.copyfile(
- hgtfile, os.path.join(tmpdir, "{im}{su}".format(im=tile[:7], su=suff))
- )
- # change to temporary directory
- os.chdir(tmpdir)
- in_temp = True
- zipfile = "{im}{su}.zip".format(im=tile, su=suff)
- hgtfile = "{im}{su}".format(im=tile[:7], su=suff)
- bilfile = tile + ".bil"
- if is_zip:
- # unzip & rename data file:
- grass.message(_("Extracting '%s'...") % infile)
- try:
- zf = zfile.ZipFile(zipfile)
- zf.extractall()
- except:
- grass.fatal(_("Unable to unzip file."))
- grass.message(_("Converting input file to BIL..."))
- os.rename(hgtfile, bilfile)
- north = tile[0]
- ll_latitude = int(tile[1:3])
- east = tile[3]
- ll_longitude = int(tile[4:7])
- # are we on the southern hemisphere? If yes, make LATITUDE negative.
- if north == "S":
- ll_latitude *= -1
- # are we west of Greenwich? If yes, make LONGITUDE negative.
- if east == "W":
- ll_longitude *= -1
- # Calculate Upper Left from Lower Left
- ulxmap = "%.1f" % ll_longitude
- # SRTM90 tile size is 1 deg:
- ulymap = "%.1f" % (ll_latitude + 1)
- if not one:
- tmpl = tmpl3sec
- elif swbd:
- grass.message(_("Attempting to import 1-arcsec SWBD data"))
- tmpl = swbd1sec
- else:
- grass.message(_("Attempting to import 1-arcsec data"))
- tmpl = tmpl1sec
- header = tmpl % (ulxmap, ulymap)
- hdrfile = tile + ".hdr"
- outf = open(hdrfile, "w")
- outf.write(header)
- outf.close()
- # create prj file: To be precise, we would need EGS96! But who really cares...
- prjfile = tile + ".prj"
- outf = open(prjfile, "w")
- outf.write(proj)
- outf.close()
- try:
- grass.run_command("r.in.gdal", input=bilfile, out=tileout)
- except:
- grass.fatal(_("Unable to import data"))
- # nice color table
- if not swbd:
- grass.run_command("r.colors", map=tileout, color="srtm")
- # write cmd history:
- grass.raster_history(tileout)
- grass.message(_("Done: generated map ") + tileout)
- grass.message(
- _("(Note: Holes in the data can be closed with 'r.fillnulls' using splines)")
- )
- if __name__ == "__main__":
- options, flags = grass.parser()
- atexit.register(cleanup)
- main()
|