Skip to content

Commit 5573fc1

Browse files
committed
Further speed improvements. Quadmesh extension code (still not as
fast as the old version, for various reasons.) Fix bugs in quadmesh masking in PDF and PS backends. svn path=/branches/transforms/; revision=4152
1 parent 630291c commit 5573fc1

File tree

10 files changed

+399
-91
lines changed

10 files changed

+399
-91
lines changed

lib/matplotlib/axes.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4788,7 +4788,8 @@ def pcolormesh(self, *args, **kwargs):
47884788
vmax = kwargs.pop('vmax', None)
47894789
shading = kwargs.pop('shading', 'flat')
47904790
edgecolors = kwargs.pop('edgecolors', 'None')
4791-
4791+
antialiased = kwargs.pop('antialiased', False)
4792+
47924793
X, Y, C = self._pcolorargs('pcolormesh', *args)
47934794
Ny, Nx = X.shape
47944795

@@ -4807,7 +4808,7 @@ def pcolormesh(self, *args, **kwargs):
48074808
showedges = 0
48084809

48094810
collection = mcoll.QuadMesh(
4810-
Nx - 1, Ny - 1, coords, showedges) # kwargs are not used
4811+
Nx - 1, Ny - 1, coords, showedges, antialiased=antialiased) # kwargs are not used
48114812
collection.set_alpha(alpha)
48124813
collection.set_array(C)
48134814
if norm is not None: assert(isinstance(norm, mcolors.Normalize))

lib/matplotlib/backend_bases.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import numpy as npy
1010
import matplotlib.cbook as cbook
1111
import matplotlib.colors as colors
12+
import matplotlib.path as path
1213
import matplotlib.transforms as transforms
1314
import matplotlib.widgets as widgets
1415
from matplotlib import rcParams
@@ -75,6 +76,30 @@ def draw_path_collection(self, master_transform, cliprect, clippath,
7576
path, transform = path_id
7677
transform = transforms.Affine2D(transform.get_matrix()).translate(xo, yo)
7778
self.draw_path(gc, path, transform, rgbFace)
79+
80+
def draw_quad_mesh(self, master_transform, cliprect, clippath,
81+
clippath_trans, meshWidth, meshHeight, coordinates,
82+
offsets, offsetTrans, facecolors, antialiased,
83+
showedges):
84+
"""
85+
This provides a fallback implementation of draw_quad_mesh that
86+
generates paths and then calls draw_path_collection.
87+
"""
88+
from matplotlib.collections import QuadMesh
89+
paths = QuadMesh.convert_mesh_to_paths(
90+
meshWidth, meshHeight, coordinates)
91+
92+
if showedges:
93+
edgecolors = npy.array([[0.0, 0.0, 0.0, 1.0]], npy.float_)
94+
linewidths = npy.array([1.0], npy.float_)
95+
else:
96+
edgecolors = linewidths = npy.array([], npy.float_)
97+
linewidths = npy.array([0.0], npy.float_)
98+
99+
return self.draw_path_collection(
100+
master_transform, cliprect, clippath, clippath_trans,
101+
paths, [], offsets, offsetTrans, facecolors, edgecolors,
102+
linewidths, [], [antialiased])
78103

79104
def _iter_collection_raw_paths(self, master_transform, paths, all_transforms):
80105
"""
@@ -158,6 +183,9 @@ def _iter_collection(self, path_ids, cliprect, clippath, clippath_trans,
158183
if Nfacecolors == 0:
159184
rgbFace = None
160185

186+
if Nedgecolors == 0:
187+
gc.set_linewidth(0.0)
188+
161189
xo, yo = 0, 0
162190
for i in xrange(N):
163191
path_id = path_ids[i % Npaths]

lib/matplotlib/backends/backend_agg.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ def __init__(self, width, height, dpi):
6666
self.draw_path = self._renderer.draw_path
6767
self.draw_markers = self._renderer.draw_markers
6868
self.draw_path_collection = self._renderer.draw_path_collection
69+
self.draw_quad_mesh = self._renderer.draw_quad_mesh
6970
self.draw_image = self._renderer.draw_image
7071
self.copy_from_bbox = self._renderer.copy_from_bbox
7172
self.restore_region = self._renderer.restore_region

lib/matplotlib/backends/backend_pdf.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -993,7 +993,7 @@ def _rgb(self, im):
993993

994994
rgba = npy.fromstring(s, npy.uint8)
995995
rgba.shape = (h, w, 4)
996-
rgb = rgba[:,:,:3]
996+
rgb = rgba[:,:,:4]
997997
return h, w, rgb.tostring()
998998

999999
def _gray(self, im, rc=0.3, gc=0.59, bc=0.11):
@@ -1601,10 +1601,12 @@ def __repr__(self):
16011601
return `d`
16021602

16031603
def _strokep(self):
1604-
return self._linewidth > 0 and self._alpha > 0
1604+
return (self._linewidth > 0 and self._alpha > 0 and
1605+
(len(self._rgb) <= 3 or self._rgb[3] != 0.0))
16051606

16061607
def _fillp(self):
1607-
return self._fillcolor is not None or self._hatch
1608+
return ((self._fillcolor is not None or self._hatch) and
1609+
(len(self._fillcolor) <= 3 or self._fillcolor[3] != 0.0))
16081610

16091611
def close_and_paint(self):
16101612
if self._strokep():

lib/matplotlib/backends/backend_ps.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -745,14 +745,20 @@ def _draw_ps(self, ps, gc, rgbFace, fill=True, stroke=True, command=None):
745745
if debugPS and command:
746746
write("% "+command+"\n")
747747

748-
self.set_linewidth(gc.get_linewidth())
749-
jint = gc.get_joinstyle()
750-
self.set_linejoin(jint)
751-
cint = gc.get_capstyle()
752-
self.set_linecap(cint)
753-
self.set_linedash(*gc.get_dashes())
754-
if self.linewidth > 0 and stroke:
755-
self.set_color(*gc.get_rgb()[:3])
748+
stroke = (stroke and gc.get_linewidth() > 0.0 and
749+
(len(gc.get_rgb()) <= 3 or gc.get_rgb()[3] != 0.0))
750+
fill = (fill and rgbFace is not None and
751+
(len(rgbFace) <= 3 or rgbFace[3] != 0.0))
752+
753+
if stroke:
754+
self.set_linewidth(gc.get_linewidth())
755+
jint = gc.get_joinstyle()
756+
self.set_linejoin(jint)
757+
cint = gc.get_capstyle()
758+
self.set_linecap(cint)
759+
self.set_linedash(*gc.get_dashes())
760+
if self.linewidth > 0 and stroke:
761+
self.set_color(*gc.get_rgb()[:3])
756762

757763
cliprect = gc.get_clip_rectangle()
758764
if cliprect:
@@ -767,7 +773,7 @@ def _draw_ps(self, ps, gc, rgbFace, fill=True, stroke=True, command=None):
767773
write(ps.strip())
768774
write("\n")
769775

770-
if rgbFace is not None and fill:
776+
if fill:
771777
#print 'rgbface', rgbFace
772778
write("gsave\n")
773779
self.set_color(store=0, *rgbFace[:3])

lib/matplotlib/collections.py

Lines changed: 61 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -376,52 +376,88 @@ class QuadMesh(Collection):
376376
at mesh coordinates (0, 0), then the one at (0, 1), then at
377377
(0, 2) .. (0, meshWidth), (1, 0), (1, 1), and so on.
378378
"""
379-
def __init__(self, meshWidth, meshHeight, coordinates, showedges):
380-
Path = mpath.Path
381-
379+
def __init__(self, meshWidth, meshHeight, coordinates, showedges, antialiased=True):
382380
Collection.__init__(self)
383381
self._meshWidth = meshWidth
384382
self._meshHeight = meshHeight
385383
self._coordinates = coordinates
386384
self._showedges = showedges
385+
self._antialiased = antialiased
387386

387+
self._paths = None
388+
389+
self._bbox = transforms.Bbox.unit()
390+
self._bbox.update_from_data_xy(coordinates.reshape(
391+
((meshWidth + 1) * (meshHeight + 1), 2)))
392+
393+
def get_paths(self, dataTrans=None):
394+
import pdb
395+
pdb.set_trace()
396+
if self._paths is None:
397+
self._paths = self.convert_mesh_to_paths(
398+
self._meshWidth, self._meshHeight, self._coordinates)
399+
return self._paths
400+
401+
#@staticmethod
402+
def convert_mesh_to_paths(meshWidth, meshHeight, coordinates):
403+
Path = mpath.Path
404+
388405
c = coordinates.reshape((meshHeight + 1, meshWidth + 1, 2))
389406
# We could let the Path constructor generate the codes for us,
390407
# but this is faster, since we know they'll always be the same
391408
codes = npy.array(
392409
[Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY],
393410
Path.code_type)
394-
411+
395412
points = npy.concatenate((
396-
c[0:-1, 0:-1],
397-
c[0:-1, 1: ],
398-
c[1: , 1: ],
399-
c[1: , 0:-1],
400-
c[0:-1, 0:-1]
401-
), axis=2)
413+
c[0:-1, 0:-1],
414+
c[0:-1, 1: ],
415+
c[1: , 1: ],
416+
c[1: , 0:-1],
417+
c[0:-1, 0:-1]
418+
), axis=2)
402419
points = points.reshape((meshWidth * meshHeight, 5, 2))
403-
self._paths = [Path(x, codes) for x in points]
404-
405-
self._bbox = transforms.Bbox.unit()
406-
self._bbox.update_from_data_xy(c.reshape(
407-
((meshWidth + 1) * (meshHeight + 1), 2)))
408-
409-
def get_paths(self, dataTrans=None):
410-
return self._paths
411-
420+
return [Path(x, codes) for x in points]
421+
convert_mesh_to_paths = staticmethod(convert_mesh_to_paths)
422+
412423
def get_datalim(self, transData):
413424
return self._bbox
414425

415426
def draw(self, renderer):
416-
self.update_scalarmappable()
427+
if not self.get_visible(): return
428+
renderer.open_group(self.__class__.__name__)
429+
transform = self.get_transform()
430+
transOffset = self._transOffset
431+
offsets = self._offsets
432+
433+
if self.have_units():
434+
if len(self._offsets):
435+
xs = self.convert_xunits(self._offsets[:0])
436+
ys = self.convert_yunits(self._offsets[:1])
437+
offsets = zip(xs, ys)
417438

418-
self._linewidths = (1,)
419-
if self._showedges:
420-
self._edgecolors = npy.array([[0.0, 0.0, 0.0, 1.0]], npy.float_)
439+
if len(offsets) == 0:
440+
offsets = npy.array([], npy.float_)
421441
else:
422-
self._edgecolors = self._facecolors
442+
offsets = npy.asarray(offsets, npy.float_)
423443

424-
Collection.draw(self, renderer)
444+
self.update_scalarmappable()
445+
446+
clippath, clippath_trans = self.get_transformed_clip_path_and_affine()
447+
if clippath_trans is not None:
448+
clippath_trans = clippath_trans.frozen()
449+
450+
assert transform.is_affine
451+
if not transOffset.is_affine:
452+
offsets = transOffset.transform_non_affine(offsets)
453+
transOffset = transOffset.get_affine()
454+
455+
renderer.draw_quad_mesh(
456+
transform.frozen(), self.clipbox, clippath, clippath_trans,
457+
self._meshWidth, self._meshHeight, self._coordinates,
458+
offsets, transOffset, self._facecolors, self._antialiased,
459+
self._showedges)
460+
renderer.close_group(self.__class__.__name__)
425461

426462
class PolyCollection(Collection):
427463
def __init__(self, verts, **kwargs):

lib/matplotlib/lines.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,10 @@ def set_data(self, *args):
388388
not_masked += 1
389389

390390
if (not_masked < 2 or
391-
((x.shape != self._xorig.shape or npy.any(x != self._xorig)) or
392-
(y.shape != self._yorig.shape or npy.any(y != self._yorig)))):
391+
(x is not self._xorig and
392+
(x.shape != self._xorig.shape or npy.any(x != self._xorig))) or
393+
(y is not self._yorig and
394+
(y.shape != self._yorig.shape or npy.any(y != self._yorig)))):
393395
self._xorig = x
394396
self._yorig = y
395397
self.recache()

0 commit comments

Comments
 (0)