Skip to content

Commit 01f43da

Browse files
committed
Collections support 2-D numerix arrays for path segments.
svn path=/trunk/matplotlib/; revision=2508
1 parent 4fa9418 commit 01f43da

File tree

14 files changed

+311
-75
lines changed

14 files changed

+311
-75
lines changed

API_CHANGES

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
Collections: PolyCollection and LineCollection now accept
2+
vertices or segments either in the original form [(x,y),
3+
(x,y), ...] or as a 2D numerix array, with X as the first column
4+
and Y as the second. Contour and quiver output the numerix
5+
form. The transforms methods Bbox.update() and
6+
Transformation.seq_xy_tups() now accept either form.
7+
18
Collections: LineCollection is now a ScalarMappable like
29
PolyCollection, etc.
310

CHANGELOG

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1+
2006-06-22 Added support for numerix 2-D arrays as alternatives to
2+
a sequence of (x,y) tuples for specifying paths in
3+
collections, quiver, contour, pcolor, transforms.
4+
Fixed contour bug involving setting limits for
5+
color mapping. Added numpy-style all() to numerix. - EF
6+
17
2006-06-20 Added custom FigureClass hook to pylab interface - see
28
examples/custom_figure_class.py
39

4-
2006-06-16 Added colormaps from gist (gist_earth, gist_stern,
10+
2006-06-16 Added colormaps from gist (gist_earth, gist_stern,
511
gist_rainbow, gist_gray, gist_yarg, gist_heat, gist_ncar) - JW
612

713
2006-06-16 Added a pointer to parent in figure canvas so you can

lib/matplotlib/axes.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
transpose, log, log10, Float, Float32, ravel, zeros,\
77
Int16, Int32, Int, Float64, ceil, indices, \
88
shape, which, where, sqrt, asum, compress, maximum, minimum, \
9-
typecode
9+
typecode, concatenate, newaxis, reshape
1010

1111
import numerix.ma as ma
1212

@@ -2093,7 +2093,7 @@ def plot(self, *args, **kwargs):
20932093

20942094
d = kwargs.copy()
20952095
scalex = d.pop('scalex', True)
2096-
scaley = d.pop('scaley', True)
2096+
scaley = d.pop('scaley', True)
20972097
if not self._hold: self.cla()
20982098
lines = []
20992099
for line in self._get_lines(*args, **d):
@@ -3665,7 +3665,15 @@ def pcolor(self, *args, **kwargs):
36653665
Y3 = compress(ravel(mask==0),ravel(ma.filled(Y[1:,1:])))
36663666
X4 = compress(ravel(mask==0),ravel(ma.filled(X[0:-1,1:])))
36673667
Y4 = compress(ravel(mask==0),ravel(ma.filled(Y[0:-1,1:])))
3668-
verts = zip(zip(X1,Y1),zip(X2,Y2),zip(X3,Y3),zip(X4,Y4))
3668+
npoly = len(X1)
3669+
xy = concatenate((X1[:,newaxis], Y1[:,newaxis],
3670+
X2[:,newaxis], Y2[:,newaxis],
3671+
X3[:,newaxis], Y3[:,newaxis],
3672+
X4[:,newaxis], Y4[:,newaxis]),
3673+
axis=1)
3674+
verts = reshape(xy, (npoly, 4, 2))
3675+
3676+
#verts = zip(zip(X1,Y1),zip(X2,Y2),zip(X3,Y3),zip(X4,Y4))
36693677

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

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

4489-
def autoscale_view(self):
4497+
def autoscale_view(self, scalex=True, scaley=True):
44904498
'set the view limits to include all the data in the axes'
44914499
self.rintd.set_bounds(0, self.get_rmax())
44924500
rmin, rmax = self.rlocator.autoscale()

lib/matplotlib/collections.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,8 @@ class PolyCollection(PatchCollection):
231231
def __init__(self, verts, **kwargs):
232232
"""
233233
verts is a sequence of ( verts0, verts1, ...) where verts_i is
234-
a sequence of xy tuples of vertices.
234+
a sequence of xy tuples of vertices, or an equivalent
235+
numerix array of shape (nv,2).
235236
See PatchCollection for kwargs.
236237
"""
237238
PatchCollection.__init__(self,**kwargs)

lib/matplotlib/colorbar.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,13 @@ def _edges(self, X, Y):
217217
'''
218218
N = nx.shape(X)[0]
219219
if self.orientation == 'vertical':
220-
return [zip(X[i], Y[i]) for i in range(1, N-1)]
220+
return nx.concatenate((X[1:N-1, nx.newaxis],
221+
Y[1:N-1, nx.newaxis]), axis=1)
222+
#return [zip(X[i], Y[i]) for i in range(1, N-1)]
221223
else:
222-
return [zip(Y[i], X[i]) for i in range(1, N-1)]
224+
return nx.concatenate((Y[1:N-1, nx.newaxis],
225+
X[1:N-1, nx.newaxis]), axis=1)
226+
#return [zip(Y[i], X[i]) for i in range(1, N-1)]
223227

224228
def _add_solids(self, X, Y, C):
225229
'''
@@ -456,7 +460,7 @@ def __init__(self, ax, mappable, **kw):
456460
kw['values'] = CS.cvalues
457461
kw['extend'] = CS.extend
458462
#kw['ticks'] = CS._levels
459-
kw.setdefault('ticks', CS._levels)
463+
kw.setdefault('ticks', CS.levels)
460464
kw['filled'] = CS.filled
461465
ColorbarBase.__init__(self, ax, **kw)
462466
if not CS.filled:

lib/matplotlib/contour.py

Lines changed: 53 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
transpose, log, log10, Float, Float32, ravel, zeros, Int16,\
1313
Int32, Int, Float64, ceil, indices, shape, which, where, sqrt,\
1414
asum, resize, reshape, add, argmin, arctan2, pi, argsort, sin,\
15-
cos, nonzero, take
15+
cos, nonzero, take, concatenate, all, newaxis
1616

1717
from mlab import linspace, meshgrid
1818
import _contour
@@ -221,8 +221,8 @@ def break_linecontour(self, linecontour, rot, labelwidth, ind):
221221

222222
slc = trans.seq_xy_tups(linecontour)
223223
x,y = slc[ind]
224-
xx= array(slc)[:,0].copy()
225-
yy=array(slc)[:,1].copy()
224+
xx= asarray(slc)[:,0].copy()
225+
yy=asarray(slc)[:,1].copy()
226226

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

259259
new_x1d, new_y1d = trans.inverse_xy_tup((new_x1, new_y1))
260260
new_x2d, new_y2d = trans.inverse_xy_tup((new_x2, new_y2))
261+
new_xy1 = array(((new_x1d, new_y1d),))
262+
new_xy2 = array(((new_x2d, new_y2d),))
261263

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

266-
if len(lc2) > 0 and (lc2[0][0] >= new_x2d) and (lc2[0][1] >= new_y2d):
267-
lc2.insert(0, (new_x2d, new_y2d))
265+
if rot > 0:
266+
if (len(lc1) > 0 and (lc1[-1][0] <= new_x1d)
267+
and (lc1[-1][1] <= new_y1d)):
268+
lc1 = concatenate((lc1, new_xy1))
269+
#lc1.append((new_x1d, new_y1d))
270+
271+
if (len(lc2) > 0 and (lc2[0][0] >= new_x2d)
272+
and (lc2[0][1] >= new_y2d)):
273+
lc2 = concatenate((new_xy2, lc2))
274+
#lc2.insert(0, (new_x2d, new_y2d))
268275
else:
269-
if len(lc1) > 0 and ((lc1[-1][0] <= new_x1d) and (lc1[-1][1] >= new_y1d)):
270-
lc1.append((new_x1d, new_y1d))
276+
if (len(lc1) > 0 and ((lc1[-1][0] <= new_x1d)
277+
and (lc1[-1][1] >= new_y1d))):
278+
lc1 = concatenate((lc1, new_xy1))
279+
#lc1.append((new_x1d, new_y1d))
271280

272-
if len(lc2) > 0 and ((lc2[0][0] >= new_x2d) and (lc2[0][1] <= new_y2d)):
273-
lc2.insert(0, (new_x2d, new_y2d))
281+
if (len(lc2) > 0 and ((lc2[0][0] >= new_x2d)
282+
and (lc2[0][1] <= new_y2d))):
283+
lc2 = concatenate((new_xy2, lc2))
284+
#lc2.insert(0, (new_x2d, new_y2d))
274285

275286
return [lc1,lc2]
276287

@@ -291,8 +302,8 @@ def locate_label(self, linecontour, labelwidth):
291302
else:
292303
ysize = labelwidth
293304

294-
XX = resize(array(linecontour)[:,0],(xsize, ysize))
295-
YY = resize(array(linecontour)[:,1],(xsize,ysize))
305+
XX = resize(asarray(linecontour)[:,0],(xsize, ysize))
306+
YY = resize(asarray(linecontour)[:,1],(xsize,ysize))
296307

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

315-
dind = list(linecontour).index((x,y))
327+
# There must be a more efficient way...
328+
lc = [tuple(l) for l in linecontour]
329+
dind = lc.index((x,y))
330+
#print 'dind', dind
331+
#dind = list(linecontour).index((x,y))
316332

317333
return x,y, rotation, dind
318334

@@ -327,14 +343,15 @@ def labels(self, inline):
327343
colors,
328344
self.label_cvalues, fslist):
329345
con = self.collections[icon]
330-
toremove = []
331-
toadd = []
332346
lw = self.get_label_width(lev, fmt, fsize)
347+
additions = []
333348
for segNum, linecontour in enumerate(con._segments):
334349
# for closed contours add one more point to
335350
# avoid division by zero
336-
if linecontour[0] == linecontour[-1]:
337-
linecontour.append(linecontour[1])
351+
if all(linecontour[0] == linecontour[-1]):
352+
linecontour = concatenate((linecontour,
353+
linecontour[1][newaxis,:]))
354+
#linecontour.append(linecontour[1])
338355
# transfer all data points to screen coordinates
339356
slc = trans.seq_xy_tups(linecontour)
340357
if self.print_label(slc,lw):
@@ -352,15 +369,9 @@ def labels(self, inline):
352369
if inline:
353370
new = self.break_linecontour(linecontour, rotation,
354371
lw, ind)
355-
toadd.extend(new)
356-
#for c in new: toadd.append(c)
357-
toremove.append(linecontour)
358-
for c in toremove:
359-
con._segments.remove(c)
360-
for c in toadd:
361-
con._segments.append(c)
362-
363-
372+
con._segments[segNum] = new[0]
373+
additions.append(new[1])
374+
con._segments.extend(additions)
364375

365376
class ContourSet(ScalarMappable, ContourLabeler):
366377
"""
@@ -443,7 +454,7 @@ def __init__(self, ax, *args, **kwargs):
443454
lowers = self._levels[:-1]
444455
uppers = self._levels[1:]
445456
for level, level_upper, color in zip(lowers, uppers, self.tcolors):
446-
nlist = C.trace(level, level_upper, points = 1,
457+
nlist = C.trace(level, level_upper, points = 0,
447458
nchunk = self.nchunk)
448459
col = PolyCollection(nlist,
449460
linewidths = (self.linewidths,),
@@ -459,7 +470,7 @@ def __init__(self, ax, *args, **kwargs):
459470
#C = _contour.Cntr(x, y, z.filled(), z.mask())
460471
C = _contour.Cntr(x, y, z.filled(), ma.getmaskorNone(z))
461472
for level, color, width in zip(self.levels, self.tcolors, tlinewidths):
462-
nlist = C.trace(level, points = 1)
473+
nlist = C.trace(level, points = 0)
463474
col = LineCollection(nlist,
464475
colors = color,
465476
linewidths = width)
@@ -625,9 +636,20 @@ def _contour_args(self, *args):
625636
if self.extend in ('both', 'max'):
626637
self._levels.append(self.zmax + 1)
627638
self._levels = asarray(self._levels)
639+
self.vmin = amin(self.levels) # alternative would be self.layers
640+
self.vmax = amax(self.levels)
641+
if self.extend in ('both', 'min') or self.clip_ends:
642+
self.vmin = 2 * self.levels[0] - self.levels[1]
643+
if self.extend in ('both', 'max') or self.clip_ends:
644+
self.vmax = 2 * self.levels[-1] - self.levels[-2]
628645
self.layers = self._levels # contour: a line is a thin layer
629646
if self.filled:
630647
self.layers = 0.5 * (self._levels[:-1] + self._levels[1:])
648+
if self.extend in ('both', 'min') or self.clip_ends:
649+
self.layers[0] = 0.5 * (self.vmin + self._levels[1])
650+
if self.extend in ('both', 'max') or self.clip_ends:
651+
self.layers[-1] = 0.5 * (self.vmax + self._levels[-2])
652+
631653
return (x, y, z)
632654

633655
def _process_colors(self):
@@ -654,13 +676,7 @@ def _process_colors(self):
654676
else:
655677
self.cvalues = self.layers
656678
if not self.norm.scaled():
657-
vmin = amin(self.levels) # alternative would be self.layers
658-
vmax = amax(self.levels)
659-
if self.extend in ('both', 'min') or self.clip_ends:
660-
vmin = 2 * self.levels[0] - self.levels[1]
661-
if self.extend in ('both', 'max') or self.clip_ends:
662-
vmax = 2 * self.levels[-1] - self.levels[-2]
663-
self.set_clim(vmin, vmax)
679+
self.set_clim(self.vmin, self.vmax)
664680
if self.extend in ('both', 'max', 'min'):
665681
self.norm.clip = False
666682
self.set_array(self.layers)

lib/matplotlib/numerix/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,22 +50,22 @@
5050
if which[0] == "numarray":
5151
#from na_imports import *
5252
from numarray import *
53-
from _na_imports import nx, inf, infinity, Infinity, Matrix, isnan
53+
from _na_imports import nx, inf, infinity, Infinity, Matrix, isnan, all
5454
from numarray.numeric import nonzero
5555
from numarray.convolve import cross_correlate, convolve
5656
import numarray
5757
version = 'numarray %s'%numarray.__version__
5858
elif which[0] == "numeric":
5959
#from nc_imports import *
6060
from Numeric import *
61-
from _nc_imports import nx, inf, infinity, Infinity, isnan
61+
from _nc_imports import nx, inf, infinity, Infinity, isnan, all
6262
from Matrix import Matrix
6363
import Numeric
6464
version = 'Numeric %s'%Numeric.__version__
6565
elif which[0] == "numpy":
6666
try:
6767
import numpy.oldnumeric as numpy
68-
from numpy.oldnumeric import *
68+
from numpy.oldnumeric import *
6969
except ImportError:
7070
import numpy
7171
from numpy import *

lib/matplotlib/numerix/_na_imports.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,15 @@ class _TypeNamespace:
2424

2525
nx = _TypeNamespace()
2626

27-
from numarray import asarray, dot, fromlist, NumArray, shape
27+
from numarray import asarray, dot, fromlist, NumArray, shape, alltrue
28+
from numarray import all as _all
29+
30+
def all(a, axis=None):
31+
'''Numpy-compatible version of all()'''
32+
if axis is None:
33+
return _all(a)
34+
return alltrue(a, axis)
35+
2836
class _Matrix(NumArray):
2937
"""_Matrix is a ported, stripped down version of the Numeric Matrix
3038
class which supplies only matrix multiplication.
@@ -34,7 +42,7 @@ def _rc(self, a):
3442
return a
3543
else:
3644
return Matrix(a)
37-
45+
3846
def __mul__(self, other):
3947
aother = asarray(other)
4048
#if len(aother.shape) == 0:

lib/matplotlib/numerix/_nc_imports.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from Numeric import array, ravel, reshape, shape
1+
from Numeric import array, ravel, reshape, shape, alltrue
22
from Numeric import Int8, UInt8, Int16, UInt16, Int32, UInt32, \
33
Float32, Float64, Complex32, Complex64, Float, Int, Complex
44
from matplotlib._isnan import isnan64 as _isnan
@@ -22,6 +22,12 @@ def isnan(a):
2222
"""y = isnan(x) returns True where x is Not-A-Number"""
2323
return reshape(array([_isnan(i) for i in ravel(a)],'b'), shape(a))
2424

25+
def all(a, axis=None):
26+
'''Numpy-compatible version of all()'''
27+
if axis is None:
28+
return alltrue(ravel(a))
29+
else:
30+
return alltrue(a, axis)
2531

2632
# inf is useful for testing infinities in results of array divisions
2733
# (which don't raise exceptions)

lib/matplotlib/pylab.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -870,7 +870,7 @@ def figure(num=None, # autoincrement if None, else integer from 1-N
870870
figManager = _pylab_helpers.Gcf.get_fig_manager(num)
871871
if figManager is None:
872872
if get_backend()=='PS': dpi = 72
873-
873+
874874
figManager = new_figure_manager(num, figsize, dpi, facecolor, edgecolor, frameon, FigureClass=FigureClass, **kwargs)
875875
_pylab_helpers.Gcf.set_active(figManager)
876876
figManager.canvas.figure.number = num

0 commit comments

Comments
 (0)