-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Stem performance boost #9565
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stem performance boost #9565
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
`StemContainer` now stores `LineCollection` | ||
------------------------------------------- | ||
|
||
`StemContainer` objects now store a `LineCollection` object instead of a list | ||
of `Line2D` objects for stem lines plotted using `ax.stem`. This gives a very | ||
large performance boost to displaying and moving `ax.stem` plots. | ||
|
||
Line segments can be extracted from the `LineCollection` using | ||
`LineCollection.get_segements()`. See the `LineCollection` documentation for | ||
other methods to retrieve the collection properties. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2370,6 +2370,9 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, | |
x = y | ||
y = np.asarray(args[0], dtype=float) | ||
args = args[1:] | ||
self._process_unit_info(xdata=x, ydata=y) | ||
x = self.convert_xunits(x) | ||
y = self.convert_yunits(y) | ||
|
||
# defaults for formats | ||
if linefmt is None: | ||
|
@@ -2421,12 +2424,12 @@ def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, | |
markerline, = self.plot(x, y, color=markercolor, linestyle=markerstyle, | ||
marker=markermarker, label="_nolegend_") | ||
|
||
stemlines = [] | ||
lines = [] | ||
for thisx, thisy in zip(x, y): | ||
l, = self.plot([thisx, thisx], [bottom, thisy], | ||
color=linecolor, linestyle=linestyle, | ||
marker=linemarker, label="_nolegend_") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happened to |
||
stemlines.append(l) | ||
lines.append(((thisx, bottom), (thisx, thisy))) | ||
stemlines = mcoll.LineCollection(lines, linestyles=linestyle, | ||
colors=linecolor, label='_nolegend_') | ||
self.add_collection(stemlines) | ||
|
||
baseline, = self.plot([np.min(x), np.max(x)], [bottom, bottom], | ||
color=basecolor, linestyle=basestyle, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -174,10 +174,17 @@ class StemContainer(Container): | |
|
||
baseline : :class:`~matplotlib.lines.Line2D` | ||
The artist of the horizontal baseline. | ||
|
||
""" | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't need to remove this line. |
||
def __init__(self, markerline_stemlines_baseline, **kwargs): | ||
''' | ||
Parameters | ||
---------- | ||
markerline_stemlines_baseline : tuple | ||
Tuple of ``(markerline, stemlines, baseline)``. | ||
``markerline`` contains the `LineCollection` of the markers, | ||
``stemlines`` is a `LineCollection` of the main lines, | ||
``baseline`` is the `Line2D` of the baseline. | ||
''' | ||
markerline, stemlines, baseline = markerline_stemlines_baseline | ||
self.markerline = markerline | ||
self.stemlines = stemlines | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -589,7 +589,6 @@ def get_ydata(self, legend, xdescent, ydescent, width, height, fontsize): | |
def create_artists(self, legend, orig_handle, | ||
xdescent, ydescent, width, height, fontsize, | ||
trans): | ||
|
||
markerline, stemlines, baseline = orig_handle | ||
|
||
xdata, xdata_marker = self.get_xdata(legend, xdescent, ydescent, | ||
|
@@ -603,31 +602,44 @@ def create_artists(self, legend, orig_handle, | |
else: | ||
bottom = self._bottom | ||
|
||
leg_markerline = Line2D(xdata_marker, ydata[:len(xdata_marker)]) | ||
self.update_prop(leg_markerline, markerline, legend) | ||
|
||
leg_stemlines = [] | ||
for thisx, thisy in zip(xdata_marker, ydata): | ||
l = Line2D([thisx, thisx], [bottom, thisy]) | ||
leg_stemlines.append(l) | ||
|
||
for lm, m in zip(leg_stemlines, stemlines): | ||
self.update_prop(lm, m, legend) | ||
# update_prop() usually takes two Line2D collections; | ||
# override temporarily to copy properties from a LineCollection | ||
orig_update_func = self._update_prop_func | ||
self._update_prop_func = self._copy_collection_props | ||
|
||
for thisx, thisy in zip(xdata_marker, ydata): | ||
thisline = Line2D([thisx, thisx], [bottom, thisy]) | ||
leg_stemlines.append(thisline) | ||
self.update_prop(thisline, stemlines, legend) | ||
# Reset update_prop_func | ||
self._update_prop_func = orig_update_func | ||
|
||
leg_baseline = Line2D([np.min(xdata), np.max(xdata)], | ||
[bottom, bottom]) | ||
|
||
self.update_prop(leg_baseline, baseline, legend) | ||
|
||
artists = [leg_markerline] | ||
artists.extend(leg_stemlines) | ||
leg_markerline = Line2D(xdata_marker, ydata[:len(xdata_marker)]) | ||
self.update_prop(leg_markerline, markerline, legend) | ||
|
||
artists = leg_stemlines | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think @anntzer would say that you can use Python 3 syntax now: |
||
artists.append(leg_baseline) | ||
artists.append(leg_markerline) | ||
|
||
for artist in artists: | ||
artist.set_transform(trans) | ||
|
||
return artists | ||
|
||
def _copy_collection_props(self, legend_handle, orig_handle): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I managed to fix the legend properties by adding this function, which kind of works. |
||
''' | ||
Method to copy properties from a LineCollection (orig_handle) to a | ||
Line2D (legend_handle). | ||
''' | ||
legend_handle._color = orig_handle.get_color()[0] | ||
|
||
|
||
class HandlerTuple(HandlerBase): | ||
""" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo segments