Skip to content

Commit

Permalink
Further speed improvements. Quadmesh extension code (still not as
Browse files Browse the repository at this point in the history
fast as the old version, for various reasons.)
Fix bugs in quadmesh masking in PDF and PS backends.

svn path=/branches/transforms/; revision=4152
  • Loading branch information
mdboom committed Nov 7, 2007
1 parent 630291c commit 5573fc1
Show file tree
Hide file tree
Showing 10 changed files with 399 additions and 91 deletions.
5 changes: 3 additions & 2 deletions lib/matplotlib/axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -4788,7 +4788,8 @@ def pcolormesh(self, *args, **kwargs):
vmax = kwargs.pop('vmax', None)
shading = kwargs.pop('shading', 'flat')
edgecolors = kwargs.pop('edgecolors', 'None')

antialiased = kwargs.pop('antialiased', False)

X, Y, C = self._pcolorargs('pcolormesh', *args)
Ny, Nx = X.shape

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

collection = mcoll.QuadMesh(
Nx - 1, Ny - 1, coords, showedges) # kwargs are not used
Nx - 1, Ny - 1, coords, showedges, antialiased=antialiased) # kwargs are not used
collection.set_alpha(alpha)
collection.set_array(C)
if norm is not None: assert(isinstance(norm, mcolors.Normalize))
Expand Down
28 changes: 28 additions & 0 deletions lib/matplotlib/backend_bases.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import numpy as npy
import matplotlib.cbook as cbook
import matplotlib.colors as colors
import matplotlib.path as path
import matplotlib.transforms as transforms
import matplotlib.widgets as widgets
from matplotlib import rcParams
Expand Down Expand Up @@ -75,6 +76,30 @@ def draw_path_collection(self, master_transform, cliprect, clippath,
path, transform = path_id
transform = transforms.Affine2D(transform.get_matrix()).translate(xo, yo)
self.draw_path(gc, path, transform, rgbFace)

def draw_quad_mesh(self, master_transform, cliprect, clippath,
clippath_trans, meshWidth, meshHeight, coordinates,
offsets, offsetTrans, facecolors, antialiased,
showedges):
"""
This provides a fallback implementation of draw_quad_mesh that
generates paths and then calls draw_path_collection.
"""
from matplotlib.collections import QuadMesh
paths = QuadMesh.convert_mesh_to_paths(
meshWidth, meshHeight, coordinates)

if showedges:
edgecolors = npy.array([[0.0, 0.0, 0.0, 1.0]], npy.float_)
linewidths = npy.array([1.0], npy.float_)
else:
edgecolors = linewidths = npy.array([], npy.float_)
linewidths = npy.array([0.0], npy.float_)

return self.draw_path_collection(
master_transform, cliprect, clippath, clippath_trans,
paths, [], offsets, offsetTrans, facecolors, edgecolors,
linewidths, [], [antialiased])

def _iter_collection_raw_paths(self, master_transform, paths, all_transforms):
"""
Expand Down Expand Up @@ -158,6 +183,9 @@ def _iter_collection(self, path_ids, cliprect, clippath, clippath_trans,
if Nfacecolors == 0:
rgbFace = None

if Nedgecolors == 0:
gc.set_linewidth(0.0)

xo, yo = 0, 0
for i in xrange(N):
path_id = path_ids[i % Npaths]
Expand Down
1 change: 1 addition & 0 deletions lib/matplotlib/backends/backend_agg.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def __init__(self, width, height, dpi):
self.draw_path = self._renderer.draw_path
self.draw_markers = self._renderer.draw_markers
self.draw_path_collection = self._renderer.draw_path_collection
self.draw_quad_mesh = self._renderer.draw_quad_mesh
self.draw_image = self._renderer.draw_image
self.copy_from_bbox = self._renderer.copy_from_bbox
self.restore_region = self._renderer.restore_region
Expand Down
8 changes: 5 additions & 3 deletions lib/matplotlib/backends/backend_pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,7 @@ def _rgb(self, im):

rgba = npy.fromstring(s, npy.uint8)
rgba.shape = (h, w, 4)
rgb = rgba[:,:,:3]
rgb = rgba[:,:,:4]
return h, w, rgb.tostring()

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

def _strokep(self):
return self._linewidth > 0 and self._alpha > 0
return (self._linewidth > 0 and self._alpha > 0 and
(len(self._rgb) <= 3 or self._rgb[3] != 0.0))

def _fillp(self):
return self._fillcolor is not None or self._hatch
return ((self._fillcolor is not None or self._hatch) and
(len(self._fillcolor) <= 3 or self._fillcolor[3] != 0.0))

def close_and_paint(self):
if self._strokep():
Expand Down
24 changes: 15 additions & 9 deletions lib/matplotlib/backends/backend_ps.py
Original file line number Diff line number Diff line change
Expand Up @@ -745,14 +745,20 @@ def _draw_ps(self, ps, gc, rgbFace, fill=True, stroke=True, command=None):
if debugPS and command:
write("% "+command+"\n")

self.set_linewidth(gc.get_linewidth())
jint = gc.get_joinstyle()
self.set_linejoin(jint)
cint = gc.get_capstyle()
self.set_linecap(cint)
self.set_linedash(*gc.get_dashes())
if self.linewidth > 0 and stroke:
self.set_color(*gc.get_rgb()[:3])
stroke = (stroke and gc.get_linewidth() > 0.0 and
(len(gc.get_rgb()) <= 3 or gc.get_rgb()[3] != 0.0))
fill = (fill and rgbFace is not None and
(len(rgbFace) <= 3 or rgbFace[3] != 0.0))

if stroke:
self.set_linewidth(gc.get_linewidth())
jint = gc.get_joinstyle()
self.set_linejoin(jint)
cint = gc.get_capstyle()
self.set_linecap(cint)
self.set_linedash(*gc.get_dashes())
if self.linewidth > 0 and stroke:
self.set_color(*gc.get_rgb()[:3])

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

if rgbFace is not None and fill:
if fill:
#print 'rgbface', rgbFace
write("gsave\n")
self.set_color(store=0, *rgbFace[:3])
Expand Down
86 changes: 61 additions & 25 deletions lib/matplotlib/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,52 +376,88 @@ class QuadMesh(Collection):
at mesh coordinates (0, 0), then the one at (0, 1), then at
(0, 2) .. (0, meshWidth), (1, 0), (1, 1), and so on.
"""
def __init__(self, meshWidth, meshHeight, coordinates, showedges):
Path = mpath.Path

def __init__(self, meshWidth, meshHeight, coordinates, showedges, antialiased=True):
Collection.__init__(self)
self._meshWidth = meshWidth
self._meshHeight = meshHeight
self._coordinates = coordinates
self._showedges = showedges
self._antialiased = antialiased

self._paths = None

self._bbox = transforms.Bbox.unit()
self._bbox.update_from_data_xy(coordinates.reshape(
((meshWidth + 1) * (meshHeight + 1), 2)))

def get_paths(self, dataTrans=None):
import pdb
pdb.set_trace()
if self._paths is None:
self._paths = self.convert_mesh_to_paths(
self._meshWidth, self._meshHeight, self._coordinates)
return self._paths

#@staticmethod
def convert_mesh_to_paths(meshWidth, meshHeight, coordinates):
Path = mpath.Path

c = coordinates.reshape((meshHeight + 1, meshWidth + 1, 2))
# We could let the Path constructor generate the codes for us,
# but this is faster, since we know they'll always be the same
codes = npy.array(
[Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY],
Path.code_type)

points = npy.concatenate((
c[0:-1, 0:-1],
c[0:-1, 1: ],
c[1: , 1: ],
c[1: , 0:-1],
c[0:-1, 0:-1]
), axis=2)
c[0:-1, 0:-1],
c[0:-1, 1: ],
c[1: , 1: ],
c[1: , 0:-1],
c[0:-1, 0:-1]
), axis=2)
points = points.reshape((meshWidth * meshHeight, 5, 2))
self._paths = [Path(x, codes) for x in points]

self._bbox = transforms.Bbox.unit()
self._bbox.update_from_data_xy(c.reshape(
((meshWidth + 1) * (meshHeight + 1), 2)))

def get_paths(self, dataTrans=None):
return self._paths

return [Path(x, codes) for x in points]
convert_mesh_to_paths = staticmethod(convert_mesh_to_paths)

def get_datalim(self, transData):
return self._bbox

def draw(self, renderer):
self.update_scalarmappable()
if not self.get_visible(): return
renderer.open_group(self.__class__.__name__)
transform = self.get_transform()
transOffset = self._transOffset
offsets = self._offsets

if self.have_units():
if len(self._offsets):
xs = self.convert_xunits(self._offsets[:0])
ys = self.convert_yunits(self._offsets[:1])
offsets = zip(xs, ys)

self._linewidths = (1,)
if self._showedges:
self._edgecolors = npy.array([[0.0, 0.0, 0.0, 1.0]], npy.float_)
if len(offsets) == 0:
offsets = npy.array([], npy.float_)
else:
self._edgecolors = self._facecolors
offsets = npy.asarray(offsets, npy.float_)

Collection.draw(self, renderer)
self.update_scalarmappable()

clippath, clippath_trans = self.get_transformed_clip_path_and_affine()
if clippath_trans is not None:
clippath_trans = clippath_trans.frozen()

assert transform.is_affine
if not transOffset.is_affine:
offsets = transOffset.transform_non_affine(offsets)
transOffset = transOffset.get_affine()

renderer.draw_quad_mesh(
transform.frozen(), self.clipbox, clippath, clippath_trans,
self._meshWidth, self._meshHeight, self._coordinates,
offsets, transOffset, self._facecolors, self._antialiased,
self._showedges)
renderer.close_group(self.__class__.__name__)

class PolyCollection(Collection):
def __init__(self, verts, **kwargs):
Expand Down
6 changes: 4 additions & 2 deletions lib/matplotlib/lines.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,8 +388,10 @@ def set_data(self, *args):
not_masked += 1

if (not_masked < 2 or
((x.shape != self._xorig.shape or npy.any(x != self._xorig)) or
(y.shape != self._yorig.shape or npy.any(y != self._yorig)))):
(x is not self._xorig and
(x.shape != self._xorig.shape or npy.any(x != self._xorig))) or
(y is not self._yorig and
(y.shape != self._yorig.shape or npy.any(y != self._yorig)))):
self._xorig = x
self._yorig = y
self.recache()
Expand Down
Loading

0 comments on commit 5573fc1

Please sign in to comment.