123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- #!/usr/bin/env python
- ############################################################################
- #
- # MODULE: r.in.wms
- #
- # AUTHOR(S): Cedric Shock, 2006
- # Pythonized 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
- #%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: wgetoptions
- #% type: string
- #% description: Additional options for wget
- #% answer: -c -t 5 -nv
- #% required : no
- #% guisection: Download
- #%end
- #%option
- #% key: curloptions
- #% type: string
- #% description: Additional options for curl
- #% answer: -C - --retry 5 -s -S
- #% required : no
- #% guisection: Download
- #%end
- #%option
- #% key: method
- #% type: string
- #% description: Reprojection method to use
- #% options:nearest,bilinear,cubic,cubicspline
- #% answer:nearest
- #% 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
- import xml.sax.handler
- HandlerBase=xml.sax.handler.ContentHandler
- from xml.sax import make_parser
- import grass
- import wms_request
- import wms_download
- class ProcessCapFile(HandlerBase):
- """
- A SAX handler for the capabilities file
- """
- def __init__(self):
- self.inTag = {}
- for tag in ('layer', 'name', 'style',
- 'title', 'srs'):
- self.inTag[tag] = False
- self.value = ''
-
- self.layers = []
-
- def startElement(self, name, attrs):
- if self.inTag.has_key(name.lower()):
- self.inTag[name.lower()] = True
-
- if name.lower() == 'layer':
- self.layers.append({})
-
- def endElement(self, name):
- if self.inTag.has_key(name.lower()):
- self.inTag[name.lower()] = False
- for tag in ('name', 'title', 'srs'):
- if name.lower() != tag:
- continue
- if self.inTag['style']:
- if not self.layers[-1].has_key('style'):
- self.layers[-1]['style'] = {}
- if not self.layers[-1]['style'].has_key(tag):
- self.layers[-1]['style'][tag] = []
- self.layers[-1]['style'][tag].append(self.value)
- elif self.inTag['layer']:
- self.layers[-1][tag] = self.value
-
- if name.lower() in ('name', 'title', 'srs'):
- self.value = ''
-
- def characters(self, ch):
- if self.inTag['name'] or \
- self.inTag['title'] or \
- self.inTag['srs']:
- self.value += ch
-
- def getLayers(self):
- """Print list of layers"""
- for ly in self.layers:
- print "LAYER: " + ly['name']
- if ly.has_key('title'):
- print " Title: " + ly['title']
- if ly.has_key('srs'):
- print " SRS: " + ly['srs']
- if ly.has_key('style'):
- for idx in range(len(ly['style']['name'])):
- print " STYLE: " + ly['style']['name'][idx]
- print " Style title: " + ly['style']['title'][idx]
-
- def list_layers():
- """Get 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'])
- cap_file = urllib.urlopen(options['mapserver'] + qstring)
- if not cap_file:
- grass.fatal("Unable to get capabilities of <%s>" % options['mapserver'])
- # parse file with sax
- cap_xml = 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")
- # 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'])
-
- if not flags['d']:
- # request data first
- request = wms_request.WMSRequest(flags, options)
- request.GetTiles()
- if not request:
- grass.fatal("WMS request failed")
-
- # 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)
-
- gdalwarp.GDALWarp(flags, options)
-
- return 0
- if __name__ == "__main__":
- options, flags = grass.parser()
- sys.exit(main())
|