-
-
Save klonuo/b05f1704127accc0a0da to your computer and use it in GitHub Desktop.
wmsimage()
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def wmsimage(self, server='http://www.gebco.net/data_and_products/gebco_web_services/web_map_service/mapserv',\ | |
request='GetMap',layers='GEBCO_08_Grid',version='1.1.1',\ | |
fmt='image/png',bgcolor='0xFFFFFF',transparent='TRUE',\ | |
xpixels=400,ypixels=None,verbose=False,**kwargs): | |
""" | |
Retrieve an image using the WMS server request and display it on | |
the map. In order to use this method, the Basemap instance must be | |
created using the ``epsg`` keyword to define the map projection, unless | |
the ``cyl`` projection is used (in which case the epsg code 4326 is | |
assumed). | |
.. tabularcolumns:: |l|L| | |
============== ==================================================== | |
Keywords Description | |
============== ==================================================== | |
server WMS server base URL (default | |
http://server.arcgisonline.com/ArcGIS). | |
request service request (default GetMap). | |
layers comma separated list of layers. | |
version WMS server version (default 1.1.1) | |
fmt response format (default 'image/png') | |
xpixels requested number of image pixels in x-direction | |
(default 400). | |
ypixels requested number of image pixels in y-direction. | |
Default (None) is to infer the number from | |
from xpixels and the aspect ratio of the | |
map projection region. | |
verbose if True, print URL used to retrieve image (default | |
False). | |
\**kwargs extra keyword arguments passed on to | |
:meth:`imshow` | |
============== ==================================================== | |
Extra keyword ``ax`` can be used to override the default axis instance. | |
returns a matplotlib.image.AxesImage instance. | |
""" | |
import urllib2 | |
if not hasattr(self,'epsg'): | |
msg = dedent(""" | |
Basemap instance must be creating using an EPSG code | |
(http://spatialreference.org) in order to use the wmsmap method""") | |
raise ValueError(msg) | |
# find the x,y values at the corner points. | |
p = pyproj.Proj(init="epsg:%s" % self.epsg, preserve_units=True) | |
xmin,ymin = p(self.llcrnrlon,self.llcrnrlat) | |
xmax,ymax = p(self.urcrnrlon,self.urcrnrlat) | |
if self.projection in _cylproj: | |
Dateline =\ | |
_geoslib.Point(self(180.,0.5*(self.llcrnrlat+self.urcrnrlat))) | |
hasDateline = Dateline.within(self._boundarypolyxy) | |
if hasDateline: | |
msg=dedent(""" | |
wmsimage cannot handle images that cross | |
the dateline for cylindrical projections.""") | |
raise ValueError(msg) | |
if self.projection == 'cyl': | |
xmin = (180./np.pi)*xmin; xmax = (180./np.pi)*xmax | |
ymin = (180./np.pi)*ymin; ymax = (180./np.pi)*ymax | |
# ypixels not given, find by scaling xpixels by the map aspect ratio. | |
if ypixels is None: | |
ypixels = int(self.aspect*xpixels) | |
#~ GetCapabilities and do raw validation on requested parameters: | |
import xml.etree.ElementTree as ET | |
try: | |
msg = '' | |
doc = ET.parse(urllib2.urlopen(server + "?SERVICE=WMS&REQUEST=GetCapabilities")) | |
#~ Check if requested format is supported by WMS server: | |
for node in doc.findall('.//Capability/Request/GetMap/Format'): | |
msg = msg + node.text + '\n' | |
if fmt == node.text: | |
msg = False | |
break | |
if msg: | |
raise ValueError('Format "%s" is not supported.\nServer supports following formats:\n%s' \ | |
% (fmt, msg)) | |
#~ Check version and projection parameter | |
sr = 'SRS'; msg = '' | |
v = doc.getroot().get('version') | |
if not version == v: | |
print 'Server reports WMS version: "%s" while request is made for version %s' \ | |
% (v, version) | |
if len(v) == 5 and int(v.replace('.','')) > 111: | |
sr = 'CRS' | |
#~ Check supported projections | |
for node in doc.findall('.//Capability/Layer/' + sr): | |
node = node.text.replace(',', '') | |
msg = msg + node + '\n' | |
if 'EPSG:' + str(self.epsg) == node: | |
msg = False | |
break | |
if msg: | |
raise ValueError('Projection "EPSG:%s" is not supported.\nServer support following projections:\n%s' \ | |
% (str(self.epsg), msg)) | |
except: | |
raise ValueError('Problem getting WMS capabilities.\nProbably wrong server address or server out of order') | |
# construct a WMS URL request. | |
basemap_url = \ | |
"%s?service=WMS&version=%s&request=%s&layers=%s&\ | |
bbox=%d,%d,%d,%d&\ | |
%s=EPSG:%s&\ | |
format=%s&\ | |
bgcolor=%s&\ | |
transparent=%s&\ | |
width=%s&\ | |
height=%s" %\ | |
(server,version,request,layers,xmin,ymin,xmax,ymax,sr,self.epsg,fmt,bgcolor,transparent,xpixels,ypixels) | |
# print URL? | |
if verbose: print basemap_url | |
#~ WMS servers seem to transfer chunked response, which imread() can't | |
#~ handle transparently. | |
#~ Transfer encoding is checked and `cStringIO` module is engaged: | |
resp = urllib2.urlopen(basemap_url) | |
if resp.headers['content-type'] == fmt: | |
if resp.headers['transfer-encoding'] == 'chunked': | |
import cStringIO | |
sio_img = cStringIO.StringIO() | |
while True: | |
chunk = resp.read() | |
if not chunk: | |
break | |
sio_img.write(chunk) | |
sio_img.seek(0) | |
wms_img = imread(sio_img) | |
sio_img.close() | |
else: | |
wms_img = imread(resp) | |
resp.close() | |
return self.imshow(wms_img, origin='upper', **kwargs) | |
elif resp.headers['content-type'] == 'application/vnd.ogc.se_xml': | |
raise ValueError(ET.parse(resp).find('.//ServiceException').text) | |
else: | |
raise ValueError('Unknown error occured, please re-check parameters') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment