Skip to content

Instantly share code, notes, and snippets.

@klonuo
Created September 6, 2012 08:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save klonuo/b05f1704127accc0a0da to your computer and use it in GitHub Desktop.
Save klonuo/b05f1704127accc0a0da to your computer and use it in GitHub Desktop.
wmsimage()
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