Thanks to visit codestin.com
Credit goes to github.com

Skip to content

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)