123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- #!/usr/bin/env python
- ############################################################################
- #
- # MODULE: r.in.wms
- #
- # AUTHOR(S): Cedric Shock, 2006
- # Upgraded for GRASS 7 by Martin Landa <landa.martin gmail.com>, 2009
- #
- # PURPOSE: To import data from web mapping servers
- # (based on Bash script by Cedric Shock)
- #
- # COPYRIGHT: (C) 2009 Martin Landa, and 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: Downloads and imports data from WMS servers.
- #% keywords: raster, import, wms
- #%end
- #%flag
- #% key: l
- #% description: List available layers and exit
- #% guisection: Request
- #%end
- #%flag
- #% key: d
- #% description: Skip to downloading (to resume downloads faster)
- #% guisection: Download
- #%end
- #%flag
- #% key: o
- #% description: Don't request transparent data
- #% guisection: Request
- #%end
- #%flag
- #% key: c
- #% description: Clean existing data out of download directory
- #% guisection: Download
- #%end
- #%flag
- #% key: k
- #% description: Keep band numbers instead of using band color names
- #% guisection: Import
- #%end
- #%flag
- #% key: p
- #% description: Don't reproject the data, just patch it
- #% guisection: Import
- #%end
- #%flag
- #% key: g
- #% label: Use GET method instead of POST data method
- #% description: This may be needed to connect to servers which lack POST capability
- #% guisection: Request
- #%end
- #%flag
- #% key: a
- #% description: Use GDAL WMS driver
- #% guisection: Request
- #%end
- #%option
- #% key: output
- #% type: string
- #% description: Name for output raster map
- #% gisprompt: new,cell,raster
- #% required : no
- #% guisection: Import
- #%end
- #%option
- #% key: mapserver
- #% type: string
- #% description: Mapserver to request data from
- #% required: yes
- #% guisection: Request
- #%end
- #%option
- #% key: layers
- #% type: string
- #% description: Layers to request from map server
- #% multiple: yes
- #% required: no
- #% guisection: Request
- #%end
- #%option
- #% key: styles
- #% type: string
- #% description: Styles to request from map server
- #% multiple: yes
- #% required: no
- #% guisection: Request
- #%end
- #%option
- #% key: srs
- #% type: string
- #% description: Source projection to request from server
- #% answer:EPSG:4326
- #% guisection: Request
- #%end
- #%option
- #% key: format
- #% type: string
- #% description: Image format requested from the server
- #% options: geotiff,tiff,jpeg,gif,png
- #% answer: geotiff
- #% required: yes
- #% guisection: Request
- #%end
- #%option
- #% key: wmsquery
- #% type:string
- #% description: Addition query options for server
- #% answer: version=1.1.1
- #% guisection: Request
- #%end
- #%option
- #% key: maxcols
- #% type: integer
- #% description: Maximum columns to request at a time
- #% answer: 1024
- #% required : yes
- #% guisection: Request
- #%end
- #%option
- #% key: maxrows
- #% type: integer
- #% description: Maximum rows to request at a time
- #% answer: 1024
- #% required : yes
- #% guisection: Request
- #%end
- #%option
- #% key: tileoptions
- #% type: string
- #% description: Additional options for r.tileset
- #% required : no
- #%end
- #%option
- #% key: region
- #% type: string
- #% description: Named region to request data for. Current region used if omitted
- #% required : no
- #% guisection: Request
- #%end
- #%option
- #% key: folder
- #% type: string
- #% description: Folder to save downloaded data to (default $GISDBASE/wms_download)
- #% required : no
- #% guisection: Download
- #%end
- #%option
- #% key: method
- #% type: string
- #% description: Reprojection method to use
- #% options:near,bilinear,cubic,cubicspline
- #% answer:near
- #% required: yes
- #% guisection: Import
- #%end
- #%option
- #% key: cap_file
- #% type: string
- #% label: Filename to save capabilities XML file to
- #% description: Requires list available layers flag
- #% required: no
- #% guisection: Request
- #%end
- import os
- import sys
- import tempfile
- import urllib
- import xml.sax
- from grass.script import core, raster as grass
- wmsPath = os.path.join(os.getenv('GISBASE'), 'etc', 'r.in.wms')
- sys.path.append(wmsPath)
- try:
- import wms_parse
- import wms_request
- import wms_download
- import gdalwarp
- import wms_gdal
- except ImportError:
- pass
- def list_layers():
- """Get list of available layers from WMS server"""
- qstring = "service=WMS&request=GetCapabilities&" + options['wmsquery']
- grass.debug("POST-data: %s" % qstring)
-
- # download capabilities file
- grass.verbose("List of layers for server <%s>:" % options['mapserver'])
- url = options['mapserver'] + '?' + qstring
- try:
- if options['cap_file']:
- cap_file, headers = urllib.urlretrieve(url, options['cap_file'])
- else:
- cap_file = urllib.urlopen(url, options['mapserver'] + '?' + qstring)
- except IOError:
- grass.fatal("Unable to get capabilities of '%s'" % options['mapserver'])
-
- # check DOCTYPE first
- if options['cap_file']:
- if headers['content-type'] != 'application/vnd.ogc.wms_xml':
- grass.fatal("Unable to get capabilities: %s" % url)
- else:
- if cap_file.info()['content-type'] != 'application/vnd.ogc.wms_xml':
- grass.fatal("Unable to get capabilities: %s" % url)
- # parse file with sax
- cap_xml = wms_parse.ProcessCapFile()
- try:
- xml.sax.parse(cap_file, cap_xml)
- except xml.sax.SAXParseException, err:
- grass.fatal("Reading capabilities failed. "
- "Unable to parse XML document: %s" % err)
-
- cap_xml.getLayers()
-
- def main():
- if flags['l']:
- # list of available layers
- list_layers()
- return 0
- elif not options['output']:
- grass.fatal("No output map specified")
-
- if options['cap_file'] and not flags['l']:
- grass.warning("Option <cap_file> ignored. It requires '-l' flag.")
-
- # set directory for download
- if not options['folder']:
- options['folder'] = os.path.join(grass.gisenv()['GISDBASE'], 'wms_download')
-
- # region settings
- if options['region']:
- if not grass.find_file(name = options['region'], element = 'windows')['name']:
- grass.fatal("Region <%s> not found" % options['region'])
- request = wms_request.WMSRequest(flags, options)
- if not flags['d']:
- # request data first
- request.GetTiles()
- if not request:
- grass.fatal("WMS request failed")
-
- if flags['a']:
- # use GDAL WMS driver
- ### TODO: use GDAL Python bindings instead
- if not wms_gdal.checkGdalWms():
- grass.fatal("GDAL WMS driver is not available")
- # create local service description XML file
- gdalWms = wms_gdal.GdalWms(options, request)
- options['input'] = gdalWms.GetFile()
- else:
- # download data
- download = wms_download.WMSDownload(flags, options)
- download.GetTiles(request.GetRequests())
-
- # list of files
- files = []
- for item in request.GetRequests():
- files.append(item['output'])
- files = ','.join(files)
- options['input'] = files
- # add flags for r.in.gdalwarp
- flags['e'] = False
- flags['c'] = True
- options['warpoptions'] = ''
-
- return gdalwarp.GDALWarp(flags, options).run()
-
- return 0
- if __name__ == "__main__":
- options, flags = grass.parser()
- sys.exit(main())
|