|
From: <js...@us...> - 2008-06-12 14:39:12
|
Revision: 5482
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5482&view=rev
Author: jswhit
Date: 2008-06-12 07:39:09 -0700 (Thu, 12 Jun 2008)
Log Message:
-----------
move all of basemap.py in here so sphinx will find docstrings.
Spruce up docstrings, adding rest formatting.
Modified Paths:
--------------
trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py
Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py
===================================================================
--- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py 2008-06-12 14:29:42 UTC (rev 5481)
+++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py 2008-06-12 14:39:09 UTC (rev 5482)
@@ -1,2 +1,3443 @@
-from basemap import __doc__, __version__
-from basemap import *
+"""
+Module for plotting data on maps with matplotlib.
+
+Contains the Basemap class (which does most of the
+heavy lifting), and the following functions:
+
+NetCDFFile: Read local and remote NetCDF datasets.
+
+interp: bilinear interpolation between rectilinear grids.
+
+shiftgrid: shifts global lat/lon grids east or west.
+
+addcyclic: Add cyclic (wraparound) point in longitude.
+
+num2date: convert from a numeric time value to a datetime object.
+
+date2num: convert from a datetime object to a numeric time value.
+"""
+from matplotlib import __version__ as _matplotlib_version
+from matplotlib.cbook import is_scalar, dedent
+# check to make sure matplotlib is not too old.
+_mpl_required_version = '0.98'
+if _matplotlib_version < _mpl_required_version:
+ msg = dedent("""
+ your matplotlib is too old - basemap requires version %s or
+ higher, you have version %s""" %
+ (_mpl_required_version,_matplotlib_version))
+ raise ImportError(msg)
+from matplotlib import rcParams, is_interactive, _pylab_helpers
+from matplotlib.collections import LineCollection
+from matplotlib.patches import Ellipse, Circle, Polygon
+from matplotlib.lines import Line2D
+from matplotlib.transforms import Bbox
+import pyproj, sys, os, math, dbflib
+from proj import Proj
+import numpy as np
+import numpy.ma as ma
+from shapelib import ShapeFile
+import _geoslib, pupynere, netcdftime
+
+# basemap data files now installed in lib/matplotlib/toolkits/basemap/data
+basemap_datadir = os.sep.join([os.path.dirname(__file__), 'data'])
+
+__version__ = '0.99'
+
+# supported map projections.
+_projnames = {'cyl' : 'Cylindrical Equidistant',
+ 'merc' : 'Mercator',
+ 'tmerc' : 'Transverse Mercator',
+ 'omerc' : 'Oblique Mercator',
+ 'mill' : 'Miller Cylindrical',
+ 'lcc' : 'Lambert Conformal',
+ 'laea' : 'Lambert Azimuthal Equal Area',
+ 'nplaea' : 'North-Polar Lambert Azimuthal',
+ 'splaea' : 'South-Polar Lambert Azimuthal',
+ 'eqdc' : 'Equidistant Conic',
+ 'aeqd' : 'Azimuthal Equidistant',
+ 'npaeqd' : 'North-Polar Azimuthal Equidistant',
+ 'spaeqd' : 'South-Polar Azimuthal Equidistant',
+ 'aea' : 'Albers Equal Area',
+ 'stere' : 'Stereographic',
+ 'npstere' : 'North-Polar Stereographic',
+ 'spstere' : 'South-Polar Stereographic',
+ 'cass' : 'Cassini-Soldner',
+ 'poly' : 'Polyconic',
+ 'ortho' : 'Orthographic',
+ 'geos' : 'Geostationary',
+ 'sinu' : 'Sinusoidal',
+ 'moll' : 'Mollweide',
+ 'robin' : 'Robinson',
+ 'gnom' : 'Gnomonic',
+ }
+supported_projections = []
+for _items in _projnames.iteritems():
+ supported_projections.append(" %-17s%-40s\n" % (_items))
+supported_projections = ''.join(supported_projections)
+
+# projection specific parameters.
+projection_params = {'cyl' : 'corners only (no width/height)',
+ 'merc' : 'corners plus lat_ts (no width/height)',
+ 'tmerc' : 'lon_0,lat_0',
+ 'omerc' : 'lon_0,lat_0,lat_1,lat_2,lon_1,lon_2,no_rot',
+ 'mill' : 'corners only (no width/height)',
+ 'lcc' : 'lon_0,lat_0,lat_1,lat_2',
+ 'laea' : 'lon_0,lat_0',
+ 'nplaea' : 'bounding_lat,lon_0,lat_0,no corners or width/height',
+ 'splaea' : 'bounding_lat,lon_0,lat_0,no corners or width/height',
+ 'eqdc' : 'lon_0,lat_0,lat_1,lat_2',
+ 'aeqd' : 'lon_0,lat_0',
+ 'npaeqd' : 'bounding_lat,lon_0,lat_0,no corners or width/height',
+ 'spaeqd' : 'bounding_lat,lon_0,lat_0,no corners or width/height',
+ 'aea' : 'lon_0,lat_0,lat_1',
+ 'stere' : 'lon_0,lat_0,lat_ts',
+ 'npstere' : 'bounding_lat,lon_0,lat_0,no corners or width/height',
+ 'spstere' : 'bounding_lat,lon_0,lat_0,no corners or width/height',
+ 'cass' : 'lon_0,lat_0',
+ 'poly' : 'lon_0,lat_0',
+ 'ortho' : 'lon_0,lat_0,llcrnrx,llcrnry,urcrnrx,urcrnry,no width/height',
+ 'geos' : 'lon_0,satellite_height,llcrnrx,llcrnry,urcrnrx,urcrnry,no width/height',
+ 'sinu' : 'lon_0,lat_0,no corners or width/height',
+ 'moll' : 'lon_0,lat_0,no corners or width/height',
+ 'robin' : 'lon_0,lat_0,no corners or width/height',
+ 'gnom' : 'lon_0,lat_0',
+ }
+
+# The __init__ docstring is pulled out here because it is so long;
+# Having it in the usual place makes it hard to get from the
+# __init__ argument list to the code that uses the arguments.
+_Basemap_init_doc = """
+
+ Sets up a basemap with specified map projection.
+ and creates the coastline data structures in native map projection
+ coordinates.
+
+ The desired projection is set with the projection keyword. Default is 'cyl'.
+ Supported projections are:
+
+ ============== ====================================================
+ Key Value Description
+ ============== ====================================================
+%(supported_projections)s
+ ============== ====================================================
+
+ For most map projections, the map projection region can either be
+ specified by setting these keywords:
+
+ ============== ====================================================
+ Keyword Description
+ ============== ====================================================
+ llcrnrlon longitude of lower left hand corner of the desired map
+ domain (degrees).
+ llcrnrlat latitude of lower left hand corner of the desired map
+ domain (degrees).
+ urcrnrlon longitude of upper right hand corner of the desired map
+ domain (degrees).
+ urcrnrlat latitude of upper right hand corner of the desired map
+ domain (degrees).
+ ============== ====================================================
+
+ or these
+
+ ============== ====================================================
+ Keyword Description
+ ============== ====================================================
+ width width of desired map domain in projection coordinates
+ (meters).
+ height height of desired map domain in projection coordinates
+ (meters).
+ lon_0 center of desired map domain (in degrees).
+ lat_0 center of desired map domain (in degrees).
+ ============== ====================================================
+
+ For 'sinu', 'moll', 'npstere', 'spstere', 'nplaea', 'splaea', 'nplaea',
+ 'splaea', 'npaeqd', 'spaeqd' or 'robin', the values of
+ llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat,width and height are ignored
+ (because either they are computed internally, or entire globe is
+ always plotted).
+
+ For the cylindrical projections('cyl','merc' and 'mill'), the default is to use
+ llcrnrlon=-180,llcrnrlat=-90, urcrnrlon=180 and urcrnrlat=90). For all other
+ projections except 'ortho' and 'geos', either the lat/lon values of the
+ corners or width and height must be specified by the user.
+
+ For 'ortho' and 'geos', the lat/lon values of the corners may be specified,
+ or the x/y values of the corners (llcrnrx,llcrnry,urcrnrx,urcrnry) in the
+ coordinate system of the global projection (with x=0,y=0 at the center
+ of the global projection). If the corners are not specified,
+ the entire globe is plotted.
+
+ Other keyword arguments:
+
+ ============== ====================================================
+ Keyword Description
+ ============== ====================================================
+ resolution resolution of boundary database to use. Can be 'c'
+ (crude), 'l' (low), 'i' (intermediate), 'h' (high),
+ 'f' (full) or None.
+ If None, no boundary data will be read in (and
+ class methods such as drawcoastlines will raise an
+ if invoked).
+ Resolution drops off by roughly 80%% between datasets.
+ Higher res datasets are much slower to draw.
+ Default 'c'. Coastline data is from the GSHHS
+ (http://www.soest.hawaii.edu/wessel/gshhs/gshhs.html).
+ State, country and river datasets from the Generic
+ Mapping Tools (http://gmt.soest.hawaii.edu).
+ area_thresh coastline or lake with an area smaller than
+ area_thresh in km^2 will not be plotted.
+ Default 10000,1000,100,10,1 for resolution
+ 'c','l','i','h','f'.
+ rsphere radius of the sphere used to define map projection
+ (default 6370997 meters, close to the arithmetic mean
+ radius of the earth). If given as a sequence, the
+ first two elements are interpreted as the radii
+ of the major and minor axes of an ellipsoid.
+ Note: sometimes an ellipsoid is specified by the
+ major axis and an 'inverse flattening parameter (if).
+ The minor axis (b) can be computed from the major axis
+ (a) and the inverse flattening parameter using the
+ the formula if = a/(a-b).
+ suppress_ticks suppress automatic drawing of axis ticks and labels
+ in map projection coordinates. Default False,
+ so parallels and meridians can be labelled instead.
+ If parallel or meridian labelling is requested
+ (using drawparallels and drawmeridians methods),
+ automatic tick labelling will be supressed even if
+ suppress_ticks=False. suppress_ticks=False
+ is useful if you want to use your own custom tick
+ formatter, or if you want to let matplotlib label
+ the axes in meters using native map projection
+ coordinates.
+ anchor determines how map is placed in axes rectangle
+ (passed to axes.set_aspect). Default is 'C',
+ which means map is centered.
+ Allowed values are
+ ['C', 'SW', 'S', 'SE', 'E', 'NE', 'N', 'NW', 'W'].
+ ax set default axes instance
+ (default None - pylab.gca() may be used
+ to get the current axes instance).
+ If you don't want pylab to be imported,
+ you can either set this to a pre-defined axes
+ instance, or use the 'ax' keyword in each Basemap
+ method call that does drawing. In the first case,
+ all Basemap method calls will draw to the same axes
+ instance. In the second case, you can draw to
+ different axes with the same Basemap instance.
+ You can also use the 'ax' keyword in individual
+ method calls to selectively override the default
+ axes instance.
+ ============== ====================================================
+
+ The following parameters are map projection parameters which all default to
+ None. Not all parameters are used by all projections, some are ignored.
+ The module variable 'projection_params' is a dictionary which
+ lists which parameters apply to which projections.
+
+ lat_ts - latitude of true scale for mercator projection, optional
+ for stereographic projection.
+
+ lat_1 - first standard parallel for lambert conformal, albers
+ equal area projection and equidistant conic projections. Latitude of one
+ of the two points on the projection centerline for oblique mercator.
+ If lat_1 is not given, but lat_0 is, lat_1 is set to lat_0 for
+ lambert conformal, albers equal area and equidistant conic.
+
+ lat_2 - second standard parallel for lambert conformal, albers
+ equal area projection and equidistant conic projections. Latitude of one
+ of the two points on the projection centerline for oblique mercator.
+ If lat_2 is not given, it is set to lat_1 for
+ lambert conformal, albers equal area and equidistant conic.
+
+ lon_1 - longitude of one of the two points on the projection centerline
+ for oblique mercator.
+
+ lon_2 - longitude of one of the two points on the projection centerline
+ for oblique mercator.
+
+ no_rot - only used by oblique mercator. If set to True, the map projection
+ coordinates will not be rotated to true North. Default is False (projection
+ coordinates are automatically rotated).
+
+ lat_0 - central latitude (y-axis origin) - used by all projections,
+ Must be equator for mercator projection.
+
+ lon_0 - central meridian (x-axis origin) - used by all projections,
+
+ boundinglat - bounding latitude for pole-centered projections (npstere,spstere,
+ nplaea,splaea,npaeqd,spaeqd). These projections are square regions centered
+ on the north or south pole. The longitude lon_0 is at 6-o'clock, and the
+ latitude circle boundinglat is tangent to the edge of the map at lon_0.
+
+ satellite_height - height of satellite (in m) above equator -
+ only relevant for geostationary projections ('geos'). Default 35,786 km.
+
+ Useful instance variables:
+
+ projection - map projection. Print the module variable
+ "supported_projections" to see a list.
+
+ aspect - map aspect ratio (size of y dimension / size of x dimension).
+
+ llcrnrlon - longitude of lower left hand corner of the desired map domain.
+
+ llcrnrlon - latitude of lower left hand corner of the desired map domain.
+
+ urcrnrlon - longitude of upper right hand corner of the desired map domain.
+
+ urcrnrlon - latitude of upper right hand corner of the desired map domain.
+
+ llcrnrx,llcrnry,urcrnrx,urcrnry - corners of map domain in projection coordinates.
+
+ rmajor,rminor - equatorial and polar radii of ellipsoid used (in meters).
+
+ resolution - resolution of boundary dataset being used ('c' for crude,
+ 'l' for low, etc.). If None, no boundary dataset is associated with the
+ Basemap instance.
+
+ srs - a string representing the 'spatial reference system' for the map
+ projection as defined by PROJ.4.
+
+ Example Usage:
+
+ >>> from mpl_toolkits.basemap import Basemap
+ >>> import numpy as np
+ >>> import matplotlib.pyplot as plt
+ >>> import matplotlib.mlab as mlab
+ >>> # read in topo data (on a regular lat/lon grid)
+ >>> etopo = mlab.load('etopo20data.gz')
+ >>> lons = mlab.load('etopo20lons.gz')
+ >>> lats = mlab.load('etopo20lats.gz')
+ >>> # create Basemap instance for Robinson projection.
+ >>> m = Basemap(projection='robin',lon_0=0.5*(lons[0]+lons[-1]))
+ >>> # compute native map projection coordinates for lat/lon grid.
+ >>> x, y = m(*np.meshgrid(lons,lats))
+ >>> # make filled contour plot.
+ >>> cs = m.contourf(x,y,etopo,30,cmap=plt.cm.jet)
+ >>> m.drawcoastlines() # draw coastlines
+ >>> m.drawmapboundary() # draw a line around the map region
+ >>> m.drawparallels(np.arange(-90.,120.,30.),labels=[1,0,0,0]) # draw parallels
+ >>> m.drawmeridians(np.arange(0.,420.,60.),labels=[0,0,0,1]) # draw meridians
+ >>> plt.title('Robinson Projection') # add a title
+ >>> plt.show()
+
+ [this example (simpletest.py) plus many others can be found in the
+ examples directory of source distribution. The "OO" version of this
+ example (which does not use pylab) is called "simpletest_oo.py".]
+""" % locals()
+
+# unsupported projection error message.
+_unsupported_projection = ["'%s' is an unsupported projection.\n"]
+_unsupported_projection.append("The supported projections are:\n")
+_unsupported_projection.append(supported_projections)
+_unsupported_projection = ''.join(_unsupported_projection)
+
+def _validated_ll(param, name, minval, maxval):
+ param = float(param)
+ if param > maxval or param < minval:
+ raise ValueError('%s must be between %f and %f degrees' %
+ (name, minval, maxval))
+ return param
+
+def _insert_validated(d, param, name, minval, maxval):
+ if param is not None:
+ d[name] = _validated_ll(param, name, minval, maxval)
+
+class Basemap(object):
+
+ def __init__(self, llcrnrlon=None, llcrnrlat=None,
+ urcrnrlon=None, urcrnrlat=None,
+ llcrnrx=None, llcrnry=None,
+ urcrnrx=None, urcrnry=None,
+ width=None, height=None,
+ projection='cyl', resolution='c',
+ area_thresh=None, rsphere=6370997.0,
+ lat_ts=None,
+ lat_1=None, lat_2=None,
+ lat_0=None, lon_0=None,
+ lon_1=None, lon_2=None,
+ no_rot=False,
+ suppress_ticks=True,
+ satellite_height=35786000,
+ boundinglat=None,
+ anchor='C',
+ ax=None):
+ # docstring is added after __init__ method definition
+
+ # where to put plot in figure (default is 'C' or center)
+ self.anchor = anchor
+ # map projection.
+ self.projection = projection
+
+ # set up projection parameter dict.
+ projparams = {}
+ projparams['proj'] = projection
+ try:
+ if rsphere[0] > rsphere[1]:
+ projparams['a'] = rsphere[0]
+ projparams['b'] = rsphere[1]
+ else:
+ projparams['a'] = rsphere[1]
+ projparams['b'] = rsphere[0]
+ except:
+ if projection == 'tmerc':
+ # use bR_a instead of R because of obscure bug
+ # in proj4 for tmerc projection.
+ projparams['bR_a'] = rsphere
+ else:
+ projparams['R'] = rsphere
+ # set units to meters.
+ projparams['units']='m'
+ # check for sane values of lon_0, lat_0, lat_ts, lat_1, lat_2
+ _insert_validated(projparams, lat_0, 'lat_0', -90, 90)
+ _insert_validated(projparams, lat_1, 'lat_1', -90, 90)
+ _insert_validated(projparams, lat_2, 'lat_2', -90, 90)
+ _insert_validated(projparams, lat_ts, 'lat_ts', -90, 90)
+ _insert_validated(projparams, lon_0, 'lon_0', -360, 720)
+ _insert_validated(projparams, lon_1, 'lon_1', -360, 720)
+ _insert_validated(projparams, lon_2, 'lon_2', -360, 720)
+ if projection == 'geos':
+ projparams['h'] = satellite_height
+ # check for sane values of projection corners.
+ using_corners = (None not in [llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat])
+ if using_corners:
+ self.llcrnrlon = _validated_ll(llcrnrlon, 'llcrnrlon', -360, 720)
+ self.urcrnrlon = _validated_ll(urcrnrlon, 'urcrnrlon', -360, 720)
+ self.llcrnrlat = _validated_ll(llcrnrlat, 'llcrnrlat', -90, 90)
+ self.urcrnrlat = _validated_ll(urcrnrlat, 'urcrnrlat', -90, 90)
+
+ # for each of the supported projections,
+ # compute lat/lon of domain corners
+ # and set values in projparams dict as needed.
+
+ if projection in ['lcc', 'eqdc', 'aea']:
+ # if lat_0 is given, but not lat_1,
+ # set lat_1=lat_0
+ if lat_1 is None and lat_0 is not None:
+ lat_1 = lat_0
+ projparams['lat_1'] = lat_1
+ if lat_1 is None or lon_0 is None:
+ raise ValueError('must specify lat_1 or lat_0 and lon_0 for %s basemap (lat_2 is optional)' % _projnames[projection])
+ if lat_2 is None:
+ projparams['lat_2'] = lat_1
+ if not using_corners:
+ if width is None or height is None:
+ raise ValueError, 'must either specify lat/lon values of corners (llcrnrlon,llcrnrlat,ucrnrlon,urcrnrlat) in degrees or width and height in meters'
+ if lon_0 is None or lat_0 is None:
+ raise ValueError, 'must specify lon_0 and lat_0 when using width, height to specify projection region'
+ llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat = _choosecorners(width,height,**projparams)
+ self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat
+ self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat
+ elif projection == 'stere':
+ if lat_0 is None or lon_0 is None:
+ raise ValueError, 'must specify lat_0 and lon_0 for Stereographic basemap (lat_ts is optional)'
+ if not using_corners:
+ if width is None or height is None:
+ raise ValueError, 'must either specify lat/lon values of corners (llcrnrlon,llcrnrlat,ucrnrlon,urcrnrlat) in degrees or width and height in meters'
+ if lon_0 is None or lat_0 is None:
+ raise ValueError, 'must specify lon_0 and lat_0 when using width, height to specify projection region'
+ llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat = _choosecorners(width,height,**projparams)
+ self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat
+ self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat
+ elif projection in ['spstere', 'npstere',
+ 'splaea', 'nplaea',
+ 'spaeqd', 'npaeqd']:
+ if boundinglat is None or lon_0 is None:
+ raise ValueError('must specify boundinglat and lon_0 for %s basemap' % _projnames[projection])
+ if projection[0] == 's':
+ sgn = -1
+ else:
+ sgn = 1
+ rootproj = projection[2:]
+ projparams['proj'] = rootproj
+ if rootproj == 'stere':
+ projparams['lat_ts'] = sgn * 90.
+ projparams['lat_0'] = sgn * 90.
+ self.llcrnrlon = lon_0 - sgn*45.
+ self.urcrnrlon = lon_0 + sgn*135.
+ proj = pyproj.Proj(projparams)
+ x,y = proj(lon_0,boundinglat)
+ lon,self.llcrnrlat = proj(math.sqrt(2.)*y,0.,inverse=True)
+ self.urcrnrlat = self.llcrnrlat
+ if width is not None or height is not None:
+ print 'warning: width and height keywords ignored for %s projection' % _projnames[projection]
+ elif projection == 'laea':
+ if lat_0 is None or lon_0 is None:
+ raise ValueError, 'must specify lat_0 and lon_0 for Lambert Azimuthal basemap'
+ if not using_corners:
+ if width is None or height is None:
+ raise ValueError, 'must either specify lat/lon values of corners (llcrnrlon,llcrnrlat,ucrnrlon,urcrnrlat) in degrees or width and height in meters'
+ if lon_0 is None or lat_0 is None:
+ raise ValueError, 'must specify lon_0 and lat_0 when using width, height to specify projection region'
+ llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat = _choosecorners(width,height,**projparams)
+ self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat
+ self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat
+ elif projection == 'merc':
+ if lat_ts is None:
+ raise ValueError, 'must specify lat_ts for Mercator basemap'
+ # clip plot region to be within -89.99S to 89.99N
+ # (mercator is singular at poles)
+ if not using_corners:
+ llcrnrlon = -180.
+ llcrnrlat = -90.
+ urcrnrlon = 180
+ urcrnrlat = 90.
+ if llcrnrlat < -89.99: llcrnrlat = -89.99
+ if llcrnrlat > 89.99: llcrnrlat = 89.99
+ if urcrnrlat < -89.99: urcrnrlat = -89.99
+ if urcrnrlat > 89.99: urcrnrlat = 89.99
+ self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat
+ self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat
+ if width is not None or height is not None:
+ print 'warning: width and height keywords ignored for %s projection' % self.projection
+ elif projection in ['tmerc','gnom','cass','poly'] :
+ if lat_0 is None or lon_0 is None:
+ raise ValueError, 'must specify lat_0 and lon_0 for Transverse Mercator, Gnomonic, Cassini-Soldnerr Polyconic basemap'
+ if not using_corners:
+ if width is None or height is None:
+ raise ValueError, 'must either specify lat/lon values of corners (llcrnrlon,llcrnrlat,ucrnrlon,urcrnrlat) in degrees or width and height in meters'
+ if lon_0 is None or lat_0 is None:
+ raise ValueError, 'must specify lon_0 and lat_0 when using width, height to specify projection region'
+ llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat = _choosecorners(width,height,**projparams)
+ self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat
+ self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat
+ elif projection == 'ortho':
+ if not projparams.has_key('R'):
+ raise ValueError, 'orthographic projection only works for perfect spheres - not ellipsoids'
+ if lat_0 is None or lon_0 is None:
+ raise ValueError, 'must specify lat_0 and lon_0 for Orthographic basemap'
+ if width is not None or height is not None:
+ print 'warning: width and height keywords ignored for %s projection' % self.projection
+ if not using_corners:
+ llcrnrlon = -180.
+ llcrnrlat = -90.
+ urcrnrlon = 180
+ urcrnrlat = 90.
+ self._fulldisk = True
+ else:
+ self._fulldisk = False
+ self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat
+ self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat
+ # FIXME: won't work for points exactly on equator??
+ if np.abs(lat_0) < 1.e-2: lat_0 = 1.e-2
+ projparams['lat_0'] = lat_0
+ elif projection == 'geos':
+ if lon_0 is None:
+ raise ValueError, 'must specify lon_0 for Geostationary basemap'
+ if width is not None or height is not None:
+ print 'warning: width and height keywords ignored for %s projection' % self.projection
+ if not using_corners:
+ llcrnrlon = -180.
+ llcrnrlat = -90.
+ urcrnrlon = 180
+ urcrnrlat = 90.
+ self._fulldisk = True
+ else:
+ self._fulldisk = False
+ self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat
+ self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat
+ elif projection in ['moll','robin','sinu']:
+ if lon_0 is None:
+ raise ValueError, 'must specify lon_0 for Robinson, Mollweide, or Sinusoidal basemap'
+ if width is not None or height is not None:
+ print 'warning: width and height keywords ignored for %s projection' % self.projection
+ llcrnrlon = -180.
+ llcrnrlat = -90.
+ urcrnrlon = 180
+ urcrnrlat = 90.
+ self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat
+ self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat
+ elif projection == 'omerc':
+ if lat_1 is None or lon_1 is None or lat_2 is None or lon_2 is None:
+ raise ValueError, 'must specify lat_1,lon_1 and lat_2,lon_2 for Oblique Mercator basemap'
+ projparams['lat_1'] = lat_1
+ projparams['lon_1'] = lon_1
+ projparams['lat_2'] = lat_2
+ projparams['lon_2'] = lon_2
+ projparams['lat_0'] = lat_0
+ if no_rot:
+ projparams['no_rot']=''
+ #if not using_corners:
+ # raise ValueError, 'cannot specify map region with width and height keywords for this projection, please specify lat/lon values of corners'
+ if not using_corners:
+ if width is None or height is None:
+ raise ValueError, 'must either specify lat/lon values of corners (llcrnrlon,llcrnrlat,ucrnrlon,urcrnrlat) in degrees or width and height in meters'
+ if lon_0 is None or lat_0 is None:
+ raise ValueError, 'must specify lon_0 and lat_0 when using width, height to specify projection region'
+ llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat = _choosecorners(width,height,**projparams)
+ self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat
+ self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat
+ elif projection == 'aeqd':
+ if lat_0 is None or lon_0 is None:
+ raise ValueError, 'must specify lat_0 and lon_0 for Azimuthal Equidistant basemap'
+ if not using_corners:
+ if width is None or height is None:
+ raise ValueError, 'must either specify lat/lon values of corners (llcrnrlon,llcrnrlat,ucrnrlon,urcrnrlat) in degrees or width and height in meters'
+ if lon_0 is None or lat_0 is None:
+ raise ValueError, 'must specify lon_0 and lat_0 when using width, height to specify projection region'
+ llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat = _choosecorners(width,height,**projparams)
+ self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat
+ self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat
+ elif projection == 'mill':
+ if not using_corners:
+ llcrnrlon = -180.
+ llcrnrlat = -90.
+ urcrnrlon = 180
+ urcrnrlat = 90.
+ self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat
+ self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat
+ if width is not None or height is not None:
+ print 'warning: width and height keywords ignored for %s projection' % self.projection
+ elif projection == 'cyl':
+ if not using_corners:
+ llcrnrlon = -180.
+ llcrnrlat = -90.
+ urcrnrlon = 180
+ urcrnrlat = 90.
+ self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat
+ self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat
+ if width is not None or height is not None:
+ print 'warning: width and height keywords ignored for %s projection' % self.projection
+ else:
+ raise ValueError(_unsupported_projection % projection)
+
+ # initialize proj4
+ proj = Proj(projparams,self.llcrnrlon,self.llcrnrlat,self.urcrnrlon,self.urcrnrlat)
+
+ # make sure axis ticks are suppressed.
+ self.noticks = suppress_ticks
+
+ # make Proj instance a Basemap instance variable.
+ self.projtran = proj
+ # copy some Proj attributes.
+ atts = ['rmajor','rminor','esq','flattening','ellipsoid','projparams']
+ for att in atts:
+ self.__dict__[att] = proj.__dict__[att]
+ # these only exist for geostationary projection.
+ if hasattr(proj,'_width'):
+ self.__dict__['_width'] = proj.__dict__['_width']
+ if hasattr(proj,'_height'):
+ self.__dict__['_height'] = proj.__dict__['_height']
+ # spatial reference string (useful for georeferencing output
+ # images with gdal_translate).
+ if hasattr(self,'_proj4'):
+ self.srs = proj._proj4.srs
+ else:
+ pjargs = []
+ for key,value in self.projparams.iteritems():
+ # 'cyl' projection translates to 'eqc' in PROJ.4
+ if projection == 'cyl' and key == 'proj':
+ value = 'eqc'
+ # ignore x_0 and y_0 settings for 'cyl' projection
+ # (they are not consistent with what PROJ.4 uses)
+ elif projection == 'cyl' and key in ['x_0','y_0']:
+ continue
+ pjargs.append('+'+key+"="+str(value)+' ')
+ self.srs = ''.join(pjargs)
+ # set instance variables defining map region.
+ self.xmin = proj.xmin
+ self.xmax = proj.xmax
+ self.ymin = proj.ymin
+ self.ymax = proj.ymax
+ if projection == 'cyl':
+ self.aspect = (self.urcrnrlat-self.llcrnrlat)/(self.urcrnrlon-self.llcrnrlon)
+ else:
+ self.aspect = (proj.ymax-proj.ymin)/(proj.xmax-proj.xmin)
+ if projection in ['geos','ortho'] and \
+ None not in [llcrnrx,llcrnry,urcrnrx,urcrnry]:
+ self.llcrnrx = llcrnrx+0.5*proj.xmax
+ self.llcrnry = llcrnry+0.5*proj.ymax
+ self.urcrnrx = urcrnrx+0.5*proj.xmax
+ self.urcrnry = urcrnry+0.5*proj.ymax
+ self._fulldisk = False
+ else:
+ self.llcrnrx = proj.llcrnrx
+ self.llcrnry = proj.llcrnry
+ self.urcrnrx = proj.urcrnrx
+ self.urcrnry = proj.urcrnry
+ # set min/max lats for projection domain.
+ if projection in ['mill','cyl','merc']:
+ self.latmin = self.llcrnrlat
+ self.latmax = self.urcrnrlat
+ elif projection in ['ortho','geos','moll','robin','sinu']:
+ self.latmin = -90.
+ self.latmax = 90.
+ else:
+ lons, lats = self.makegrid(101,101)
+ self.latmin = lats.min()
+ self.latmax = lats.max()
+
+ # if ax == None, pyplot.gca may be used.
+ self.ax = ax
+ self.lsmask = None
+
+ # set defaults for area_thresh.
+ self.resolution = resolution
+ if area_thresh is None and resolution is not None:
+ if resolution == 'c':
+ area_thresh = 10000.
+ elif resolution == 'l':
+ area_thresh = 1000.
+ elif resolution == 'i':
+ area_thresh = 100.
+ elif resolution == 'h':
+ area_thresh = 10.
+ elif resolution == 'f':
+ area_thresh = 1.
+ else:
+ raise ValueError, "boundary resolution must be one of 'c','l','i','h' or 'f'"
+ self.area_thresh = area_thresh
+ # define map boundary polygon (in lat/lon coordinates)
+ self._boundarypolyll, self._boundarypolyxy = self._getmapboundary()
+ # read in coastline polygons, only keeping those that
+ # intersect map boundary polygon.
+ if self.resolution is not None:
+ self.coastsegs, self.coastpolygontypes = self._readboundarydata('gshhs')
+ # reformat for use in matplotlib.patches.Polygon.
+ self.coastpolygons = []
+ # also, split coastline segments that jump across entire plot.
+ coastsegs = []
+ for seg in self.coastsegs:
+ x, y = zip(*seg)
+ self.coastpolygons.append((x,y))
+ x = np.array(x,np.float64); y = np.array(y,np.float64)
+ xd = (x[1:]-x[0:-1])**2
+ yd = (y[1:]-y[0:-1])**2
+ dist = np.sqrt(xd+yd)
+ split = dist > 5000000.
+ if np.sum(split) and self.projection not in ['merc','cyl','mill']:
+ ind = (np.compress(split,np.squeeze(split*np.indices(xd.shape)))+1).tolist()
+ iprev = 0
+ ind.append(len(xd))
+ for i in ind:
+ # don't add empty lists.
+ if len(range(iprev,i)):
+ coastsegs.append(zip(x[iprev:i],y[iprev:i]))
+ iprev = i
+ else:
+ coastsegs.append(seg)
+ self.coastsegs = coastsegs
+ # set __init__'s docstring
+ __init__.__doc__ = _Basemap_init_doc
+
+ def __call__(self,x,y,inverse=False):
+ """
+ Calling a Basemap class instance with the arguments lon, lat will
+ convert lon/lat (in degrees) to x/y native map projection
+ coordinates (in meters). If optional keyword 'inverse' is
+ True (default is False), the inverse transformation from x/y
+ to lon/lat is performed.
+
+ For cylindrical equidistant projection ('cyl'), this
+ does nothing (i.e. x,y == lon,lat).
+
+ For non-cylindrical projections, the inverse transformation
+ always returns longitudes between -180 and 180 degrees. For
+ cylindrical projections (self.projection == 'cyl','mill' or 'merc')
+ the inverse transformation will return longitudes between
+ self.llcrnrlon and self.llcrnrlat.
+
+ input arguments lon, lat can be either scalar floats or N arrays.
+ """
+ return self.projtran(x,y,inverse=inverse)
+
+ def makegrid(self,nx,ny,returnxy=False):
+ """
+ return arrays of shape (ny,nx) containing lon,lat coordinates of
+ an equally spaced native projection grid.
+
+ if returnxy = True, the x,y values of the grid are returned also.
+ """
+ return self.projtran.makegrid(nx,ny,returnxy=returnxy)
+
+ def _readboundarydata(self,name):
+ """
+ read boundary data, clip to map projection region.
+ """
+ msg = dedent("""
+ Unable to open boundary dataset file. Only the 'crude', 'low',
+ 'intermediate' and 'high' resolution datasets are installed by default.
+ If you are requesting a 'full' resolution dataset, you may need to
+ download and install those files separately
+ (see the basemap README for details).""")
+ try:
+ bdatfile = open(os.path.join(basemap_datadir,name+'_'+self.resolution+'.dat'),'rb')
+ bdatmetafile = open(os.path.join(basemap_datadir,name+'meta_'+self.resolution+'.dat'),'r')
+ except:
+ raise IOError, msg
+ polygons = []
+ polygon_types = []
+ # coastlines are polygons, other boundaries are line segments.
+ if name == 'gshhs':
+ Shape = _geoslib.Polygon
+ else:
+ Shape = _geoslib.LineString
+ # see if map projection region polygon contains a pole.
+ NPole = _geoslib.Point(self(0.,90.))
+ SPole = _geoslib.Point(self(0.,-90.))
+ boundarypolyxy = self._boundarypolyxy
+ boundarypolyll = self._boundarypolyll
+ hasNP = NPole.within(boundarypolyxy)
+ hasSP = SPole.within(boundarypolyxy)
+ containsPole = hasNP or hasSP
+ # these projections cannot cross pole.
+ if containsPole and\
+ self.projection in ['merc','mill','cyl','robin','moll','sinu','geos']:
+ #self.projection in ['tmerc','omerc','cass','merc','mill','cyl','robin','moll','sinu','geos']:
+ raise ValueError('%s projection cannot cross pole'%(self.projection))
+ # make sure orthographic projection has containsPole=True
+ # we will compute the intersections in stereographic
+ # coordinates, then transform to orthographic.
+ if self.projection == 'ortho' and name == 'gshhs':
+ containsPole = True
+ lon_0=self.projparams['lon_0']
+ lat_0=self.projparams['lat_0']
+ re = self.projparams['R']
+ # center of stereographic projection restricted to be
+ # nearest one of 6 points on the sphere (every 90 deg lat/lon).
+ lon0 = 90.*(np.around(lon_0/90.))
+ lat0 = 90.*(np.around(lat_0/90.))
+ if np.abs(int(lat0)) == 90: lon0=0.
+ maptran = pyproj.Proj(proj='stere',lon_0=lon0,lat_0=lat0,R=re)
+ # boundary polygon for orthographic projection
+ # in stereographic coorindates.
+ b = self._boundarypolyll.boundary
+ blons = b[:,0]; blats = b[:,1]
+ b[:,0], b[:,1] = maptran(blons, blats)
+ boundarypolyxy = _geoslib.Polygon(b)
+ for line in bdatmetafile:
+ linesplit = line.split()
+ area = float(linesplit[1])
+ south = float(linesplit[3])
+ north = float(linesplit[4])
+ if area < 0.: area = 1.e30
+ useit = self.latmax>=south and self.latmin<=north and area>self.area_thresh
+ if useit:
+ type = int(linesplit[0])
+ npts = int(linesplit[2])
+ offsetbytes = int(linesplit[5])
+ bytecount = int(linesplit[6])
+ bdatfile.seek(offsetbytes,0)
+ # read in binary string convert into an npts by 2
+ # numpy array (first column is lons, second is lats).
+ polystring = bdatfile.read(bytecount)
+ # binary data is little endian.
+ b = np.array(np.fromstring(polystring,dtype='<f4'),'f8')
+ b.shape = (npts,2)
+ b2 = b.copy()
+ # if map boundary polygon is a valid one in lat/lon
+ # coordinates (i.e. it does not contain either pole),
+ # the intersections of the boundary geometries
+ # and the map projection region can be computed before
+ # transforming the boundary geometry to map projection
+ # coordinates (this saves time, especially for small map
+ # regions and high-resolution boundary geometries).
+ if not containsPole:
+ # close Antarctica.
+ if name == 'gshhs' and south < -68 and area > 10000:
+ lons = b[:,0]
+ lats = b[:,1]
+ lons2 = lons[:-2][::-1]
+ lats2 = lats[:-2][::-1]
+ lons1 = lons2 - 360.
+ lons3 = lons2 + 360.
+ lons = lons1.tolist()+lons2.tolist()+lons3.tolist()
+ lats = lats2.tolist()+lats2.tolist()+lats2.tolist()
+ lonstart,latstart = lons[0], lats[0]
+ lonend,latend = lons[-1], lats[-1]
+ lons.insert(0,lonstart)
+ lats.insert(0,-90.)
+ lons.append(lonend)
+ lats.append(-90.)
+ b = np.empty((len(lons),2),np.float64)
+ b[:,0] = lons; b[:,1] = lats
+ poly = _geoslib.Polygon(b)
+ antart = True
+ else:
+ poly = Shape(b)
+ antart = False
+ # create duplicate polygons shifted by -360 and +360
+ # (so as to properly treat polygons that cross
+ # Greenwich meridian).
+ if not antart:
+ b2[:,0] = b[:,0]-360
+ poly1 = Shape(b2)
+ b2[:,0] = b[:,0]+360
+ poly2 = Shape(b2)
+ polys = [poly1,poly,poly2]
+ else: # Antartica already extends from -360 to +720.
+ polys = [poly]
+ for poly in polys:
+ # if polygon instersects map projection
+ # region, process it.
+ if poly.intersects(boundarypolyll):
+ # if geometry intersection calculation fails,
+ # just move on.
+ try:
+ geoms = poly.intersection(boundarypolyll)
+ except:
+ continue
+ # iterate over geometries in intersection.
+ for psub in geoms:
+ # only coastlines are polygons,
+ # which have a 'boundary' attribute.
+ # otherwise, use 'coords' attribute
+ # to extract coordinates.
+ b = psub.boundary
+ blons = b[:,0]; blats = b[:,1]
+ # transformation from lat/lon to
+ # map projection coordinates.
+ bx, by = self(blons, blats)
+ polygons.append(zip(bx,by))
+ polygon_types.append(type)
+ # if map boundary polygon is not valid in lat/lon
+ # coordinates, compute intersection between map
+ # projection region and boundary geometries in map
+ # projection coordinates.
+ else:
+ # transform coordinates from lat/lon
+ # to map projection coordinates.
+ # special case for ortho, compute coastline polygon
+ # vertices in stereographic coords.
+ if name == 'gshhs' and self.projection == 'ortho':
+ b[:,0], b[:,1] = maptran(b[:,0], b[:,1])
+ else:
+ b[:,0], b[:,1] = self(b[:,0], b[:,1])
+ goodmask = np.logical_and(b[:,0]<1.e20,b[:,1]<1.e20)
+ # if less than two points are valid in
+ # map proj coords, skip this geometry.
+ if np.sum(goodmask) <= 1: continue
+ if name != 'gshhs':
+ # if not a polygon,
+ # just remove parts of geometry that are undefined
+ # in this map projection.
+ bx = np.compress(goodmask, b[:,0])
+ by = np.compress(goodmask, b[:,1])
+ # for orthographic projection, all points
+ # outside map projection region are eliminated
+ # with the above step, so we're done.
+ if self.projection == 'ortho':
+ polygons.append(zip(bx,by))
+ polygon_types.append(type)
+ continue
+ # create a GEOS geometry object.
+ poly = Shape(b)
+ # if geometry instersects map projection
+ # region, and doesn't have any invalid points, process it.
+ if goodmask.all() and poly.intersects(boundarypolyxy):
+ # if geometry intersection calculation fails,
+ # just move on.
+ try:
+ geoms = poly.intersection(boundarypolyxy)
+ except:
+ continue
+ # iterate over geometries in intersection.
+ for psub in geoms:
+ b = psub.boundary
+ # if projection == 'ortho',
+ # transform polygon from stereographic
+ # to orthographic coordinates.
+ if self.projection == 'ortho':
+ # if coastline polygon covers more than 99%
+ # of map region for fulldisk projection,
+ # it's probably bogus, so skip it.
+ areafrac = psub.area()/boundarypolyxy.area()
+ if name == 'gshhs' and\
+ self._fulldisk and\
+ areafrac > 0.99: continue
+ # inverse transform from stereographic
+ # to lat/lon.
+ b[:,0], b[:,1] = maptran(b[:,0], b[:,1], inverse=True)
+ # orthographic.
+ b[:,0], b[:,1]= self(b[:,0], b[:,1])
+ polygons.append(zip(b[:,0],b[:,1]))
+ polygon_types.append(type)
+ return polygons, polygon_types
+
+ def _getmapboundary(self):
+ """
+ create map boundary polygon (in lat/lon and x/y coordinates)
+ """
+ nx = 100
+ ny = 100
+ maptran = self
+ if self.projection in ['ortho','geos']:
+ # circular region.
+ thetas = np.linspace(0.,2.*np.pi,2*nx*ny)[:-1]
+ if self.projection == 'ortho':
+ rminor = self.rmajor
+ rmajor = self.rmajor
+ else:
+ rminor = self._height
+ rmajor = self._width
+ x = rmajor*np.cos(thetas) + rmajor
+ y = rminor*np.sin(thetas) + rminor
+ b = np.empty((len(x),2),np.float64)
+ b[:,0]=x; b[:,1]=y
+ boundaryxy = _geoslib.Polygon(b)
+ # compute proj instance for full disk, if necessary.
+ if not self._fulldisk:
+ projparms = self.projparams.copy()
+ del projparms['x_0']
+ del projparms['y_0']
+ if self.projection == 'ortho':
+ llcrnrx = -self.rmajor
+ llcrnry = -self.rmajor
+ urcrnrx = -llcrnrx
+ urcrnry = -llcrnry
+ else:
+ llcrnrx = -self._width
+ llcrnry = -self._height
+ urcrnrx = -llcrnrx
+ urcrnry = -llcrnry
+ projparms['x_0']=-llcrnrx
+ projparms['y_0']=-llcrnry
+ maptran = pyproj.Proj(projparms)
+ elif self.projection in ['moll','robin','sinu']:
+ # quasi-elliptical region.
+ lon_0 = self.projparams['lon_0']
+ # left side
+ lats1 = np.linspace(-89.9,89.9,ny).tolist()
+ lons1 = len(lats1)*[lon_0-179.9]
+ # top.
+ lons2 = np.linspace(lon_0-179.9,lon_0+179.9,nx).tolist()
+ lats2 = len(lons2)*[89.9]
+ # right side
+ lats3 = np.linspace(89.9,-89.9,ny).tolist()
+ lons3 = len(lats3)*[lon_0+179.9]
+ # bottom.
+ lons4 = np.linspace(lon_0+179.9,lon_0-179.9,nx).tolist()
+ lats4 = len(lons4)*[-89.9]
+ lons = np.array(lons1+lons2+lons3+lons4,np.float64)
+ lats = np.array(lats1+lats2+lats3+lats4,np.float64)
+ x, y = maptran(lons,lats)
+ b = np.empty((len(x),2),np.float64)
+ b[:,0]=x; b[:,1]=y
+ boundaryxy = _geoslib.Polygon(b)
+ else: # all other projections are rectangular.
+ # left side (x = xmin, ymin <= y <= ymax)
+ yy = np.linspace(self.ymin, self.ymax, ny)[:-1]
+ x = len(yy)*[self.xmin]; y = yy.tolist()
+ # top (y = ymax, xmin <= x <= xmax)
+ xx = np.linspace(self.xmin, self.xmax, nx)[:-1]
+ x = x + xx.tolist()
+ y = y + len(xx)*[self.ymax]
+ # right side (x = xmax, ymin <= y <= ymax)
+ yy = np.linspace(self.ymax, self.ymin, ny)[:-1]
+ x = x + len(yy)*[self.xmax]; y = y + yy.tolist()
+ # bottom (y = ymin, xmin <= x <= xmax)
+ xx = np.linspace(self.xmax, self.xmin, nx)[:-1]
+ x = x + xx.tolist()
+ y = y + len(xx)*[self.ymin]
+ x = np.array(x,np.float64)
+ y = np.array(y,np.float64)
+ b = np.empty((4,2),np.float64)
+ b[:,0]=[self.xmin,self.xmin,self.xmax,self.xmax]
+ b[:,1]=[self.ymin,self.ymax,self.ymax,self.ymin]
+ boundaryxy = _geoslib.Polygon(b)
+ if self.projection in ['mill','merc','cyl']:
+ # make sure map boundary doesn't quite include pole.
+ if self.urcrnrlat > 89.9999:
+ urcrnrlat = 89.9999
+ else:
+ urcrnrlat = self.urcrnrlat
+ if self.llcrnrlat < -89.9999:
+ llcrnrlat = -89.9999
+ else:
+ llcrnrlat = self.llcrnrlat
+ lons = [self.llcrnrlon, self.llcrnrlon, self.urcrnrlon, self.urcrnrlon]
+ lats = [llcrnrlat, urcrnrlat, urcrnrlat, llcrnrlat]
+ x, y = self(lons, lats)
+ b = np.empty((len(x),2),np.float64)
+ b[:,0]=x; b[:,1]=y
+ boundaryxy = _geoslib.Polygon(b)
+ else:
+ if self.projection not in ['moll','robin','sinu']:
+ lons, lats = maptran(x,y,inverse=True)
+ # fix lons so there are no jumps.
+ n = 1
+ lonprev = lons[0]
+ for lon,lat in zip(lons[1:],lats[1:]):
+ if np.abs(lon-lonprev) > 90.:
+ if lonprev < 0:
+ lon = lon - 360.
+ else:
+ lon = lon + 360
+ lons[n] = lon
+ lonprev = lon
+ n = n + 1
+ b = np.empty((len(lons),2),np.float64)
+ b[:,0]=lons; b[:,1]=lats
+ boundaryll = _geoslib.Polygon(b)
+ return boundaryll, boundaryxy
+
+
+ def drawmapboundary(self,color='k',linewidth=1.0,fill_color=None,\
+ zorder=None,ax=None):
+ """
+ draw boundary around map projection region, optionally
+ filling interior of region.
+
+ linewidth - line width for boundary (default 1.)
+
+ color - color of boundary line (default black)
+
+ fill_color - fill the map region background with this
+ color (default is no fill or fill with axis background color).
+
+ zorder - sets the zorder for filling map background
+ (default 0).
+
+ ax - axes instance to use (default None, use default axes
+ instance).
+
+ returns PatchCollection representing map boundary.
+ """
+ # get current axes instance (if none specified).
+ if ax is None and self.ax is None:
+ try:
+ ax = plt.gca()
+ except:
+ import matplotlib.pyplot as plt
+ ax = plt.gca()
+ elif ax is None and self.ax is not None:
+ ax = self.ax
+ limb = None
+ if self.projection == 'ortho':
+ limb = Circle((self.rmajor,self.rmajor),self.rmajor)
+ elif self.projection == 'geos':
+ limb = Ellipse((self._width,self._height),2.*self._width,2.*self._height)
+ if self.projection in ['ortho','geos'] and self._fulldisk:
+ # elliptical region.
+ ax.add_patch(limb)
+ if fill_color is None:
+ limb.set_fill(False)
+ else:
+ limb.set_facecolor(fill_color)
+ limb.set_zorder(0)
+ limb.set_edgecolor(color)
+ limb.set_linewidth(linewidth)
+ limb.set_clip_on(False)
+ if zorder is not None:
+ limb.set_zorder(zorder)
+ elif self.projection in ['moll','robin','sinu']: # elliptical region.
+ nx = 100; ny = 100
+ # quasi-elliptical region.
+ lon_0 = self.projparams['lon_0']
+ # left side
+ lats1 = np.linspace(-89.9,89.9,ny).tolist()
+ lons1 = len(lats1)*[lon_0-179.9]
+ # top.
+ lons2 = np.linspace(lon_0-179.9,lon_0+179.9,nx).tolist()
+ lats2 = len(lons2)*[89.9]
+ # right side
+ lats3 = np.linspace(89.9,-89.9,ny).tolist()
+ lons3 = len(lats3)*[lon_0+179.9]
+ # bottom.
+ lons4 = np.linspace(lon_0+179.9,lon_0-179.9,nx).tolist()
+ lats4 = len(lons4)*[-89.9]
+ lons = np.array(lons1+lons2+lons3+lons4,np.float64)
+ lats = np.array(lats1+lats2+lats3+lats4,np.float64)
+ x, y = self(lons,lats)
+ xy = zip(x,y)
+ limb = Polygon(xy,edgecolor=color,linewidth=linewidth)
+ ax.add_patch(limb)
+ if fill_color is None:
+ limb.set_fill(False)
+ else:
+ limb.set_facecolor(fill_color)
+ limb.set_zorder(0)
+ limb.set_clip_on(False)
+ if zorder is not None:
+ limb.set_zorder(zorder)
+ else: # all other projections are rectangular.
+ ax.axesPatch.set_linewidth(linewidth)
+ if self.projection not in ['geos','ortho']:
+ if fill_color is None:
+ ax.axesPatch.set_facecolor(ax.get_axis_bgcolor())
+ else:
+ ax.axesPatch.set_facecolor(fill_color)
+ ax.axesPatch.set_zorder(0)
+ ax.axesPatch.set_edgecolor(color)
+ ax.set_frame_on(True)
+ if zorder is not None:
+ ax.axesPatch.set_zorder(zorder)
+ else:
+ ax.axesPatch.set_facecolor(ax.get_axis_bgcolor())
+ ax.axesPatch.set_edgecolor(color)
+ ax.set_frame_on(True)
+ if zorder is not None:
+ ax.axesPatch.set_zorder(zorder)
+ # for geos or ortho projections, also
+ # draw and fill map projection limb, clipped
+ # to rectangular region.
+ ax.add_patch(limb)
+ if fill_color is None:
+ limb.set_fill(False)
+ else:
+ limb.set_facecolor(fill_color)
+ limb.set_zorder(0)
+ limb.set_edgecolor(color)
+ limb.set_linewidth(linewidth)
+ if zorder is not None:
+ limb.set_zorder(zorder)
+ limb.set_clip_on(True)
+ # set axes limits to fit map region.
+ self.set_axes_limits(ax=ax)
+ return limb
+
+ def fillcontinents(self,color='0.8',lake_color=None,ax=None,zorder=None):
+ """
+ Fill continents.
+
+ color - color to fill continents (default gray).
+
+ lake_color - color to fill inland lakes (default axes background).
+
+ ax - axes instance (overrides default axes instance).
+
+ zorder - sets the zorder for the continent polygons (if not specified,
+ uses default zorder for a Polygon patch). Set to zero if you want to paint
+ over the filled continents).
+
+ After filling continents, lakes are re-filled with axis background color.
+
+ returns Polygon object.
+ """
+ if self.resolution is None:
+ raise AttributeError, 'there are no boundary datasets associated with this Basemap instance'
+ # get current axes instance (if none specified).
+ if ax is None and self.ax is None:
+ try:
+ ax = plt.gca()
+ except:
+ import matplotlib.pyplot as plt
+ ax = plt.gca()
+ elif ax is None and self.ax is not None:
+ ax = self.ax
+ # get axis background color.
+ axisbgc = ax.get_axis_bgcolor()
+ npoly = 0
+ for x,y in self.coastpolygons:
+ xa = np.array(x,np.float32)
+ ya = np.array(y,np.float32)
+ # check to see if all four corners of domain in polygon (i...
[truncated message content] |