Skip to content

Commit

Permalink
Collections support 2-D numerix arrays for path segments.
Browse files Browse the repository at this point in the history
svn path=/trunk/matplotlib/; revision=2508
  • Loading branch information
efiring committed Jun 22, 2006
1 parent 4fa9418 commit 01f43da
Show file tree
Hide file tree
Showing 14 changed files with 311 additions and 75 deletions.
7 changes: 7 additions & 0 deletions API_CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
Collections: PolyCollection and LineCollection now accept
vertices or segments either in the original form [(x,y),
(x,y), ...] or as a 2D numerix array, with X as the first column
and Y as the second. Contour and quiver output the numerix
form. The transforms methods Bbox.update() and
Transformation.seq_xy_tups() now accept either form.

Collections: LineCollection is now a ScalarMappable like
PolyCollection, etc.

Expand Down
8 changes: 7 additions & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
2006-06-22 Added support for numerix 2-D arrays as alternatives to
a sequence of (x,y) tuples for specifying paths in
collections, quiver, contour, pcolor, transforms.
Fixed contour bug involving setting limits for
color mapping. Added numpy-style all() to numerix. - EF

2006-06-20 Added custom FigureClass hook to pylab interface - see
examples/custom_figure_class.py

2006-06-16 Added colormaps from gist (gist_earth, gist_stern,
2006-06-16 Added colormaps from gist (gist_earth, gist_stern,
gist_rainbow, gist_gray, gist_yarg, gist_heat, gist_ncar) - JW

2006-06-16 Added a pointer to parent in figure canvas so you can
Expand Down
16 changes: 12 additions & 4 deletions lib/matplotlib/axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
transpose, log, log10, Float, Float32, ravel, zeros,\
Int16, Int32, Int, Float64, ceil, indices, \
shape, which, where, sqrt, asum, compress, maximum, minimum, \
typecode
typecode, concatenate, newaxis, reshape

import numerix.ma as ma

Expand Down Expand Up @@ -2093,7 +2093,7 @@ def plot(self, *args, **kwargs):

d = kwargs.copy()
scalex = d.pop('scalex', True)
scaley = d.pop('scaley', True)
scaley = d.pop('scaley', True)
if not self._hold: self.cla()
lines = []
for line in self._get_lines(*args, **d):
Expand Down Expand Up @@ -3665,7 +3665,15 @@ def pcolor(self, *args, **kwargs):
Y3 = compress(ravel(mask==0),ravel(ma.filled(Y[1:,1:])))
X4 = compress(ravel(mask==0),ravel(ma.filled(X[0:-1,1:])))
Y4 = compress(ravel(mask==0),ravel(ma.filled(Y[0:-1,1:])))
verts = zip(zip(X1,Y1),zip(X2,Y2),zip(X3,Y3),zip(X4,Y4))
npoly = len(X1)
xy = concatenate((X1[:,newaxis], Y1[:,newaxis],
X2[:,newaxis], Y2[:,newaxis],
X3[:,newaxis], Y3[:,newaxis],
X4[:,newaxis], Y4[:,newaxis]),
axis=1)
verts = reshape(xy, (npoly, 4, 2))

#verts = zip(zip(X1,Y1),zip(X2,Y2),zip(X3,Y3),zip(X4,Y4))

C = compress(ravel(mask==0),ravel(ma.filled(C[0:Nx-1,0:Ny-1])))

Expand Down Expand Up @@ -4486,7 +4494,7 @@ def grid(self, b):
'Set the axes grids on or off; b is a boolean'
self._gridOn = b

def autoscale_view(self):
def autoscale_view(self, scalex=True, scaley=True):
'set the view limits to include all the data in the axes'
self.rintd.set_bounds(0, self.get_rmax())
rmin, rmax = self.rlocator.autoscale()
Expand Down
3 changes: 2 additions & 1 deletion lib/matplotlib/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,8 @@ class PolyCollection(PatchCollection):
def __init__(self, verts, **kwargs):
"""
verts is a sequence of ( verts0, verts1, ...) where verts_i is
a sequence of xy tuples of vertices.
a sequence of xy tuples of vertices, or an equivalent
numerix array of shape (nv,2).
See PatchCollection for kwargs.
"""
PatchCollection.__init__(self,**kwargs)
Expand Down
10 changes: 7 additions & 3 deletions lib/matplotlib/colorbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,13 @@ def _edges(self, X, Y):
'''
N = nx.shape(X)[0]
if self.orientation == 'vertical':
return [zip(X[i], Y[i]) for i in range(1, N-1)]
return nx.concatenate((X[1:N-1, nx.newaxis],
Y[1:N-1, nx.newaxis]), axis=1)
#return [zip(X[i], Y[i]) for i in range(1, N-1)]
else:
return [zip(Y[i], X[i]) for i in range(1, N-1)]
return nx.concatenate((Y[1:N-1, nx.newaxis],
X[1:N-1, nx.newaxis]), axis=1)
#return [zip(Y[i], X[i]) for i in range(1, N-1)]

def _add_solids(self, X, Y, C):
'''
Expand Down Expand Up @@ -456,7 +460,7 @@ def __init__(self, ax, mappable, **kw):
kw['values'] = CS.cvalues
kw['extend'] = CS.extend
#kw['ticks'] = CS._levels
kw.setdefault('ticks', CS._levels)
kw.setdefault('ticks', CS.levels)
kw['filled'] = CS.filled
ColorbarBase.__init__(self, ax, **kw)
if not CS.filled:
Expand Down
90 changes: 53 additions & 37 deletions lib/matplotlib/contour.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
transpose, log, log10, Float, Float32, ravel, zeros, Int16,\
Int32, Int, Float64, ceil, indices, shape, which, where, sqrt,\
asum, resize, reshape, add, argmin, arctan2, pi, argsort, sin,\
cos, nonzero, take
cos, nonzero, take, concatenate, all, newaxis

from mlab import linspace, meshgrid
import _contour
Expand Down Expand Up @@ -221,8 +221,8 @@ def break_linecontour(self, linecontour, rot, labelwidth, ind):

slc = trans.seq_xy_tups(linecontour)
x,y = slc[ind]
xx= array(slc)[:,0].copy()
yy=array(slc)[:,1].copy()
xx= asarray(slc)[:,0].copy()
yy=asarray(slc)[:,1].copy()

#indices which are under the label
inds=nonzero(((xx < x+xlabel) & (xx > x-xlabel)) &
Expand Down Expand Up @@ -258,19 +258,30 @@ def break_linecontour(self, linecontour, rot, labelwidth, ind):

new_x1d, new_y1d = trans.inverse_xy_tup((new_x1, new_y1))
new_x2d, new_y2d = trans.inverse_xy_tup((new_x2, new_y2))
new_xy1 = array(((new_x1d, new_y1d),))
new_xy2 = array(((new_x2d, new_y2d),))

if rot > 0:
if len(lc1) > 0 and (lc1[-1][0] <= new_x1d) and (lc1[-1][1] <= new_y1d):
lc1.append((new_x1d, new_y1d))

if len(lc2) > 0 and (lc2[0][0] >= new_x2d) and (lc2[0][1] >= new_y2d):
lc2.insert(0, (new_x2d, new_y2d))
if rot > 0:
if (len(lc1) > 0 and (lc1[-1][0] <= new_x1d)
and (lc1[-1][1] <= new_y1d)):
lc1 = concatenate((lc1, new_xy1))
#lc1.append((new_x1d, new_y1d))

if (len(lc2) > 0 and (lc2[0][0] >= new_x2d)
and (lc2[0][1] >= new_y2d)):
lc2 = concatenate((new_xy2, lc2))
#lc2.insert(0, (new_x2d, new_y2d))
else:
if len(lc1) > 0 and ((lc1[-1][0] <= new_x1d) and (lc1[-1][1] >= new_y1d)):
lc1.append((new_x1d, new_y1d))
if (len(lc1) > 0 and ((lc1[-1][0] <= new_x1d)
and (lc1[-1][1] >= new_y1d))):
lc1 = concatenate((lc1, new_xy1))
#lc1.append((new_x1d, new_y1d))

if len(lc2) > 0 and ((lc2[0][0] >= new_x2d) and (lc2[0][1] <= new_y2d)):
lc2.insert(0, (new_x2d, new_y2d))
if (len(lc2) > 0 and ((lc2[0][0] >= new_x2d)
and (lc2[0][1] <= new_y2d))):
lc2 = concatenate((new_xy2, lc2))
#lc2.insert(0, (new_x2d, new_y2d))

return [lc1,lc2]

Expand All @@ -291,8 +302,8 @@ def locate_label(self, linecontour, labelwidth):
else:
ysize = labelwidth

XX = resize(array(linecontour)[:,0],(xsize, ysize))
YY = resize(array(linecontour)[:,1],(xsize,ysize))
XX = resize(asarray(linecontour)[:,0],(xsize, ysize))
YY = resize(asarray(linecontour)[:,1],(xsize,ysize))

yfirst = YY[:,0]
ylast = YY[:,-1]
Expand All @@ -305,14 +316,19 @@ def locate_label(self, linecontour, labelwidth):
L=sqrt((xlast-xfirst)**2+(ylast-yfirst)**2)
dist = add.reduce(([(abs(s)[i]/L[i]) for i in range(xsize)]),-1)
x,y,ind = self.get_label_coords(dist, XX, YY, ysize, labelwidth)
#print 'ind, x, y', ind, x, y
angle = arctan2(ylast - yfirst, xlast - xfirst)
rotation = angle[ind]*180/pi
if rotation > 90:
rotation = rotation -180
if rotation < -90:
rotation = 180 + rotation

dind = list(linecontour).index((x,y))
# There must be a more efficient way...
lc = [tuple(l) for l in linecontour]
dind = lc.index((x,y))
#print 'dind', dind
#dind = list(linecontour).index((x,y))

return x,y, rotation, dind

Expand All @@ -327,14 +343,15 @@ def labels(self, inline):
colors,
self.label_cvalues, fslist):
con = self.collections[icon]
toremove = []
toadd = []
lw = self.get_label_width(lev, fmt, fsize)
additions = []
for segNum, linecontour in enumerate(con._segments):
# for closed contours add one more point to
# avoid division by zero
if linecontour[0] == linecontour[-1]:
linecontour.append(linecontour[1])
if all(linecontour[0] == linecontour[-1]):
linecontour = concatenate((linecontour,
linecontour[1][newaxis,:]))
#linecontour.append(linecontour[1])
# transfer all data points to screen coordinates
slc = trans.seq_xy_tups(linecontour)
if self.print_label(slc,lw):
Expand All @@ -352,15 +369,9 @@ def labels(self, inline):
if inline:
new = self.break_linecontour(linecontour, rotation,
lw, ind)
toadd.extend(new)
#for c in new: toadd.append(c)
toremove.append(linecontour)
for c in toremove:
con._segments.remove(c)
for c in toadd:
con._segments.append(c)


con._segments[segNum] = new[0]
additions.append(new[1])
con._segments.extend(additions)

class ContourSet(ScalarMappable, ContourLabeler):
"""
Expand Down Expand Up @@ -443,7 +454,7 @@ def __init__(self, ax, *args, **kwargs):
lowers = self._levels[:-1]
uppers = self._levels[1:]
for level, level_upper, color in zip(lowers, uppers, self.tcolors):
nlist = C.trace(level, level_upper, points = 1,
nlist = C.trace(level, level_upper, points = 0,
nchunk = self.nchunk)
col = PolyCollection(nlist,
linewidths = (self.linewidths,),
Expand All @@ -459,7 +470,7 @@ def __init__(self, ax, *args, **kwargs):
#C = _contour.Cntr(x, y, z.filled(), z.mask())
C = _contour.Cntr(x, y, z.filled(), ma.getmaskorNone(z))
for level, color, width in zip(self.levels, self.tcolors, tlinewidths):
nlist = C.trace(level, points = 1)
nlist = C.trace(level, points = 0)
col = LineCollection(nlist,
colors = color,
linewidths = width)
Expand Down Expand Up @@ -625,9 +636,20 @@ def _contour_args(self, *args):
if self.extend in ('both', 'max'):
self._levels.append(self.zmax + 1)
self._levels = asarray(self._levels)
self.vmin = amin(self.levels) # alternative would be self.layers
self.vmax = amax(self.levels)
if self.extend in ('both', 'min') or self.clip_ends:
self.vmin = 2 * self.levels[0] - self.levels[1]
if self.extend in ('both', 'max') or self.clip_ends:
self.vmax = 2 * self.levels[-1] - self.levels[-2]
self.layers = self._levels # contour: a line is a thin layer
if self.filled:
self.layers = 0.5 * (self._levels[:-1] + self._levels[1:])
if self.extend in ('both', 'min') or self.clip_ends:
self.layers[0] = 0.5 * (self.vmin + self._levels[1])
if self.extend in ('both', 'max') or self.clip_ends:
self.layers[-1] = 0.5 * (self.vmax + self._levels[-2])

return (x, y, z)

def _process_colors(self):
Expand All @@ -654,13 +676,7 @@ def _process_colors(self):
else:
self.cvalues = self.layers
if not self.norm.scaled():
vmin = amin(self.levels) # alternative would be self.layers
vmax = amax(self.levels)
if self.extend in ('both', 'min') or self.clip_ends:
vmin = 2 * self.levels[0] - self.levels[1]
if self.extend in ('both', 'max') or self.clip_ends:
vmax = 2 * self.levels[-1] - self.levels[-2]
self.set_clim(vmin, vmax)
self.set_clim(self.vmin, self.vmax)
if self.extend in ('both', 'max', 'min'):
self.norm.clip = False
self.set_array(self.layers)
Expand Down
6 changes: 3 additions & 3 deletions lib/matplotlib/numerix/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,22 @@
if which[0] == "numarray":
#from na_imports import *
from numarray import *
from _na_imports import nx, inf, infinity, Infinity, Matrix, isnan
from _na_imports import nx, inf, infinity, Infinity, Matrix, isnan, all
from numarray.numeric import nonzero
from numarray.convolve import cross_correlate, convolve
import numarray
version = 'numarray %s'%numarray.__version__
elif which[0] == "numeric":
#from nc_imports import *
from Numeric import *
from _nc_imports import nx, inf, infinity, Infinity, isnan
from _nc_imports import nx, inf, infinity, Infinity, isnan, all
from Matrix import Matrix
import Numeric
version = 'Numeric %s'%Numeric.__version__
elif which[0] == "numpy":
try:
import numpy.oldnumeric as numpy
from numpy.oldnumeric import *
from numpy.oldnumeric import *
except ImportError:
import numpy
from numpy import *
Expand Down
12 changes: 10 additions & 2 deletions lib/matplotlib/numerix/_na_imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,15 @@ class _TypeNamespace:

nx = _TypeNamespace()

from numarray import asarray, dot, fromlist, NumArray, shape
from numarray import asarray, dot, fromlist, NumArray, shape, alltrue
from numarray import all as _all

def all(a, axis=None):
'''Numpy-compatible version of all()'''
if axis is None:
return _all(a)
return alltrue(a, axis)

class _Matrix(NumArray):
"""_Matrix is a ported, stripped down version of the Numeric Matrix
class which supplies only matrix multiplication.
Expand All @@ -34,7 +42,7 @@ def _rc(self, a):
return a
else:
return Matrix(a)

def __mul__(self, other):
aother = asarray(other)
#if len(aother.shape) == 0:
Expand Down
8 changes: 7 additions & 1 deletion lib/matplotlib/numerix/_nc_imports.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from Numeric import array, ravel, reshape, shape
from Numeric import array, ravel, reshape, shape, alltrue
from Numeric import Int8, UInt8, Int16, UInt16, Int32, UInt32, \
Float32, Float64, Complex32, Complex64, Float, Int, Complex
from matplotlib._isnan import isnan64 as _isnan
Expand All @@ -22,6 +22,12 @@ def isnan(a):
"""y = isnan(x) returns True where x is Not-A-Number"""
return reshape(array([_isnan(i) for i in ravel(a)],'b'), shape(a))

def all(a, axis=None):
'''Numpy-compatible version of all()'''
if axis is None:
return alltrue(ravel(a))
else:
return alltrue(a, axis)

# inf is useful for testing infinities in results of array divisions
# (which don't raise exceptions)
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/pylab.py
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,7 @@ def figure(num=None, # autoincrement if None, else integer from 1-N
figManager = _pylab_helpers.Gcf.get_fig_manager(num)
if figManager is None:
if get_backend()=='PS': dpi = 72

figManager = new_figure_manager(num, figsize, dpi, facecolor, edgecolor, frameon, FigureClass=FigureClass, **kwargs)
_pylab_helpers.Gcf.set_active(figManager)
figManager.canvas.figure.number = num
Expand Down
Loading

0 comments on commit 01f43da

Please sign in to comment.