8000 Add a fast path for NumPy arrays to Collection.set_verts · matplotlib/matplotlib@95977d6 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 95977d6

Browse files
committed
Add a fast path for NumPy arrays to Collection.set_verts
This reduces the run time for larger 3D plots by over a second on some toy examples.
1 parent baaec37 commit 95977d6

File tree

2 files changed

+40
-15
lines changed

2 files changed

+40
-15
lines changed

lib/matplotlib/collections.py

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,23 +1090,37 @@ def set_verts(self, verts, closed=True):
10901090
Whether the polygon should be closed by adding a CLOSEPOLY
10911091
connection at the end.
10921092
"""
1093+
self.stale = True
10931094
if isinstance(verts, np.ma.MaskedArray):
10941095
verts = verts.astype(float).filled(np.nan)
1095-
# This is much faster than having Path do it one at a time.
1096-
if closed:
1097-
self._paths = []
1098-
for xy in verts:
1099-
if len(xy):
1100-
if isinstance(xy, np.ma.MaskedArray):
1101-
xy = np.ma.concatenate([xy, xy[:1]])
1102-
else:
1103-
xy = np.concatenate([xy, xy[:1]])
1104-
self._paths.append(mpath.Path(xy, closed=True))
1105-
else:
1106-
self._paths.append(mpath.Path(xy))
1107-
else:
1096+
1097+
# No need to do anything fancy if the path isn't closed.
1098+
if not closed:
11081099
self._paths = [mpath.Path(xy) for xy in verts]
1109-
self.stale = True
1100+
return
1101+
1102+
# Fast path for arrays
1103+
if isinstance(verts, np.ndarray):
1104+
verts_pad = np.concatenate((verts, verts[:, :1]), axis=1)
1105+
# Creating the codes once is much faster than having Path do it
1106+
# separately each time by passing closed=True.
1107+
codes = np.empty(verts_pad.shape[1], dtype=mpath.Path.code_type)
1108+
codes[:] = mpath.Path.LINETO
1109+
codes[0] = mpath.Path.MOVETO
1110+
codes[-1] = mpath.Path.CLOSEPOLY
1111+
self._paths = [mpath.Path(xy, codes) for xy in verts_pad]
1112+
return
1113+
1114+
self._paths = []
1115+
for xy in verts:
1116+
if len(xy):
1117+
if isinstance(xy, np.ma.MaskedArray):
1118+
xy = np.ma.concatenate([xy, xy[:1]])
1119+
else:
1120+
xy = np.concatenate([xy, xy[:1]])
1121+
self._paths.append(mpath.Path(xy, closed=True))
1122+
else:
1123+
self._paths.append(mpath.Path(xy))
11101124

11111125
set_paths = set_verts
11121126

lib/matplotlib/tests/test_collections.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
import matplotlib.pyplot as plt
1313
import matplotlib.collections as mcollections
1414
import matplotlib.transforms as mtransforms
15-
from matplotlib.collections import Collection, LineCollection, EventCollection
15+
from matplotlib.collections import (Collection, LineCollection,
16+
EventCollection, PolyCollection)
1617
from matplotlib.testing.decorators import image_comparison
1718

1819

@@ -612,3 +613,13 @@ def test_EventCollection_nosort():
612613
arr = np.array([3, 2, 1, 10])
613614
coll = EventCollection(arr)
614615
np.testing.assert_array_equal(arr, np.array([3, 2, 1, 10]))
616+
617+
618+
def test_collection_set_verts_array():
619+
verts = np.arange(80, dtype=np.double).reshape(10, 4, 2)
620+
col_arr = PolyCollection(verts)
621+
col_list = PolyCollection(list(verts))
622+
assert len(col_arr._paths) == len(col_list._paths)
623+
for ap, lp in zip(col_arr._paths, col_list._paths):
624+
assert np.array_equal(ap._vertices, lp._vertices)
625+
assert np.array_equal(ap._codes, lp._codes)

0 commit comments

Comments
 (0)
0