diff --git a/examples/README b/examples/README index 3a2af55ce..889154fb0 100644 --- a/examples/README +++ b/examples/README @@ -144,3 +144,5 @@ ploticos.py demonstrates plotting on unstructured grids. lic_demo.py shows how to use vectorplot scikit to visualize vector fields with Line Integral Convolutions (LIC). + +hexbin_demo.py shows how to plot scattered data using matplotlib hexbin function. diff --git a/examples/hexbin_demo.py b/examples/hexbin_demo.py new file mode 100644 index 000000000..a7f1fd854 --- /dev/null +++ b/examples/hexbin_demo.py @@ -0,0 +1,62 @@ +# example showing how to plot scattered data with hexbin. +from numpy.random import uniform +import matplotlib.pyplot as plt +import numpy as np +from mpl_toolkits.basemap import Basemap + +# create north polar stereographic basemap +m = Basemap(lon_0=270, boundinglat=20, projection='npstere',round=True) + +# number of points to plot. +npts = 10000 +bins = 40 +# generate random points on a sphere, +# so that every small area on the sphere is expected +# to have the same number of points. +# http://mathworld.wolfram.com/SpherePointPicking.html +u = uniform(0.,1.,size=npts) +v = uniform(0.,1.,size=npts) +lons1 = 360.*u +lats1 = (180./np.pi)*np.arccos(2*v-1) - 90. +# toss points outside of map region. +lats = np.compress(lats1 > 20, lats1) +lons = np.compress(lats1 > 20, lons1) +# convert to map projection coordinates. +x, y = m(lons, lats) +# function to plot at those points. +xscaled = 4.*(x-0.5*(m.xmax-m.xmin))/m.xmax +yscaled = 4.*(y-0.5*(m.ymax-m.ymin))/m.ymax +z = xscaled*np.exp(-xscaled**2-yscaled**2) + +# make plot using hexbin +fig = plt.figure(figsize=(12,5)) +ax = fig.add_subplot(121) +CS = plt.hexbin(x,y,C=z,gridsize=bins,cmap=plt.cm.jet) +# draw coastlines, lat/lon lines. +m.drawcoastlines() +m.drawparallels(np.arange(0,81,20)) +m.drawmeridians(np.arange(-180,181,60)) +m.colorbar() # draw colorbar +plt.title('hexbin demo') + +# use histogram2d instead of hexbin. +ax = fig.add_subplot(122) +#m = Basemap(lon_0=270, boundinglat=20, projection='npstere',round=True) +bincount, xedges, yedges = np.histogram2d(x, y, bins=bins) +mask = bincount == 0 +# reset zero values to one to avoid divide-by-zero +bincount = np.where(bincount == 0, 1, bincount) +H, xedges, yedges = np.histogram2d(x, y, bins=bins, weights=z) +H = np.ma.masked_where(mask, H/bincount) +# set color of masked values to white (hexbin does this by default) +palette = plt.cm.jet +palette.set_bad('white', 1.0) +CS = m.pcolormesh(xedges,yedges,H.T,shading='flat',cmap=palette) +# draw coastlines, lat/lon lines. +m.drawcoastlines() +m.drawparallels(np.arange(0,81,20)) +m.drawmeridians(np.arange(-180,181,60)) +m.colorbar() # draw colorbar +plt.title('histogram2d demo') + +plt.show() diff --git a/lib/mpl_toolkits/basemap/__init__.py b/lib/mpl_toolkits/basemap/__init__.py index 62e0a1508..3a6fee864 100644 --- a/lib/mpl_toolkits/basemap/__init__.py +++ b/lib/mpl_toolkits/basemap/__init__.py @@ -887,14 +887,6 @@ def __init__(self, llcrnrlon=None, llcrnrlat=None, if type == 2: self.lakepolygons.append(_geoslib.Polygon(b)) #if type == 3: self.islandinlakepolygons.append(_geoslib.Polygon(b)) #if type == 4: self.lakeinislandinlakepolygons.append(_geoslib.Polygon(b)) - # set clipping path for round polar plots. - if (self.projection.startswith('np') or - self.projection.startswith('sp') or - self.projection == 'ortho') and self.round: - self.clipcircle =\ - Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), - radius=0.5*(self.xmax-self.xmin),fc='none') - self.round = True # set __init__'s docstring __init__.__doc__ = _Basemap_init_doc @@ -1383,7 +1375,6 @@ def drawmapboundary(self,color='k',linewidth=1.0,fill_color=None,\ limb.set_zorder(zorder) elif self.round: ax.set_frame_on(False) - #limb = self.clipcircle limb = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), radius=0.5*(self.xmax-self.xmin),fc='none') ax.add_patch(limb) @@ -1523,11 +1514,13 @@ def fillcontinents(self,color='0.8',lake_color=None,ax=None,zorder=None): self.set_axes_limits(ax=ax) # clip continent polygons for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) for poly in polys: - poly.set_clip_path(self.clipcircle) + poly.set_clip_path(c) return polys def drawcoastlines(self,linewidth=1.,color='k',antialiased=1,ax=None,zorder=None): @@ -1562,10 +1555,12 @@ def drawcoastlines(self,linewidth=1.,color='k',antialiased=1,ax=None,zorder=None coastlines.set_zorder(zorder) # clip coastlines for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) - coastlines.set_clip_path(self.clipcircle) + coastlines.set_clip_path(c) ax.add_collection(coastlines) # set axes limits to fit map region. self.set_axes_limits(ax=ax) @@ -1609,10 +1604,12 @@ def drawcountries(self,linewidth=0.5,color='k',antialiased=1,ax=None,zorder=None ax.add_collection(countries) # clip countries for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) - countries.set_clip_path(self.clipcircle) + countries.set_clip_path(c) # set axes limits to fit map region. self.set_axes_limits(ax=ax) return countries @@ -1655,10 +1652,12 @@ def drawstates(self,linewidth=0.5,color='k',antialiased=1,ax=None,zorder=None): ax.add_collection(states) # clip states for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) - states.set_clip_path(self.clipcircle) + states.set_clip_path(c) # set axes limits to fit map region. self.set_axes_limits(ax=ax) return states @@ -1701,10 +1700,12 @@ def drawrivers(self,linewidth=0.5,color='k',antialiased=1,ax=None,zorder=None): ax.add_collection(rivers) # clip rivers for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) - rivers.set_clip_path(self.clipcircle) + rivers.set_clip_path(c) # set axes limits to fit map region. self.set_axes_limits(ax=ax) return rivers @@ -1869,10 +1870,12 @@ def readshapefile(self,shapefile,name,drawbounds=True,zorder=None, ax.add_collection(lines) # clip boundaries for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) - lines.set_clip_path(self.clipcircle) + lines.set_clip_path(c) # set axes limits to fit map region. self.set_axes_limits(ax=ax) info = info + (lines,) @@ -2151,13 +2154,15 @@ def drawparallels(self,circles,color='k',linewidth=1.,zorder=None, \ pardict = _dict(linecolls) # clip parallels for round polar plots (and delete labels). if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) for par in pardict: lines,labs = pardict[par] for l in lines: - l.set_clip_path(self.clipcircle) + l.set_clip_path(c) return pardict def drawmeridians(self,meridians,color='k',linewidth=1., zorder=None,\ @@ -2398,8 +2403,10 @@ def addlon(meridians,madd): meridict = _dict(linecolls) # for round polar plots, clip meridian lines and label them. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) # label desired? label = False @@ -2409,7 +2416,7 @@ def addlon(meridians,madd): lines,labs = meridict[merid] # clip lines. for l in lines: - l.set_clip_path(self.clipcircle) + l.set_clip_path(c) if not label: continue # label lonlab = _setlonlab(fmt,merid,labelstyle) @@ -2510,10 +2517,12 @@ def tissot(self,lon_0,lat_0,radius_deg,npts,ax=None,**kwargs): ax.add_patch(poly) # clip polygons for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) - poly.set_clip_path(self.clipcircle) + poly.set_clip_path(c) # set axes limits to fit map region. self.set_axes_limits(ax=ax) return poly @@ -2895,10 +2904,12 @@ def scatter(self, *args, **kwargs): plt.sci(ret) # clip for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) - ret.set_clip_path(self.clipcircle) + ret.set_clip_path(c) # set axes limits to fit map region. self.set_axes_limits(ax=ax) return ret @@ -2926,10 +2937,12 @@ def plot(self, *args, **kwargs): ax.hold(b) # clip for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) - ret.set_clip_path(self.clipcircle) + ret.set_clip_path(c) # set axes limits to fit map region. self.set_axes_limits(ax=ax) return ret @@ -2969,10 +2982,12 @@ def imshow(self, *args, **kwargs): plt.sci(ret) # clip image for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) - ret.set_clip_path(self.clipcircle) + ret.set_clip_path(c) # set axes limits to fit map region. self.set_axes_limits(ax=ax) return ret @@ -3041,12 +3056,17 @@ def pcolor(self,x,y,data,tri=False,**kwargs): plt.sci(ret) # clip for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) - ret.set_clip_path(self.clipcircle) + ret.set_clip_path(c) # set axes limits to fit map region. self.set_axes_limits(ax=ax) + if self.round: + # for some reason, frame gets turned on. + ax.set_frame_on(False) return ret def pcolormesh(self,x,y,data,**kwargs): @@ -3075,12 +3095,17 @@ def pcolormesh(self,x,y,data,**kwargs): plt.sci(ret) # clip for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) - ret.set_clip_path(self.clipcircle) + ret.set_clip_path(c) # set axes limits to fit map region. self.set_axes_limits(ax=ax) + if self.round: + # for some reason, frame gets turned on. + ax.set_frame_on(False) return ret def contour(self,x,y,data,*args,**kwargs): @@ -3163,11 +3188,13 @@ def contour(self,x,y,data,*args,**kwargs): plt.sci(CS) # clip for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) for cntr in CS.collections: - cntr.set_clip_path(self.clipcircle) + cntr.set_clip_path(c) # set axes limits to fit map region. self.set_axes_limits(ax=ax) return CS @@ -3265,11 +3292,13 @@ def contourf(self,x,y,data,*args,**kwargs): self.set_axes_limits(ax=ax) # clip for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) for cntr in CS.collections: - cntr.set_clip_path(self.clipcircle) + cntr.set_clip_path(c) return CS def quiver(self, x, y, u, v, *args, **kwargs): @@ -3297,10 +3326,12 @@ def quiver(self, x, y, u, v, *args, **kwargs): plt.sci(ret) # clip for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) - ret.set_clip_path(self.clipcircle) + ret.set_clip_path(c) # set axes limits to fit map region. self.set_axes_limits(ax=ax) return ret @@ -3348,10 +3379,12 @@ def barbs(self, x, y, u, v, *args, **kwargs): # set axes limits to fit map region. # clip for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) - ret.set_clip_path(self.clipcircle) + ret.set_clip_path(c) self.set_axes_limits(ax=ax) return retnh,retsh @@ -3492,10 +3525,12 @@ def drawlsmask(self,land_color="0.8",ocean_color="w",lsmask=None, im = self.imshow(rgba,interpolation='nearest',ax=ax,**kwargs) # clip for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) - im.set_clip_path(self.clipcircle) + im.set_clip_path(c) return im def bluemarble(self,ax=None,scale=None,**kwargs): @@ -3709,10 +3744,12 @@ def warpimage(self,image="bluemarble",scale=None,**kwargs): im = self.imshow(self._bm_rgba,ax=ax,**kwargs) # clip for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) - im.set_clip_path(self.clipcircle) + im.set_clip_path(c) return im def drawmapscale(self,lon,lat,lon0,lat0,length,barstyle='simple',\ @@ -3989,11 +4026,13 @@ def nightshade(self,date,color="k",delta=0.25,alpha=0.5,ax=None,zorder=2): c.set_zorder(zorder) # clip for round polar plots. if self.round: - if self.clipcircle not in ax.patches: - p = ax.add_patch(self.clipcircle) + c = Circle((0.5*(self.xmax+self.xmin),0.5*(self.ymax+self.ymin)), + radius=0.5*(self.xmax-self.xmin),fc='none') + if c not in ax.patches: + p = ax.add_patch(c) p.set_clip_on(False) for cntr in CS.collections: - cntr.set_clip_path(self.clipcircle) + cntr.set_clip_path(c) return CS def _check_ax(self):