Skip to content

Only autoscale_view() when needed, not after every plotting call. #13593

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

Merged
merged 1 commit into from
May 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions doc/api/next_api_changes/2019-03-04-AL.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Autoscaling changes
```````````````````

Matplotlib used to recompute autoscaled limits after every plotting
(``plot()``, ``bar()``, etc.) call. It now only does so when actually
rendering the canvas, or when the user queries the Axes limits. This is a
major performance improvement for plots with a large number of artists.

In particular, this means that artists added manually with `Axes.add_line`,
`Axes.add_patch`, etc. will be taken into account by the autoscale, even
without an explicit call to `Axes.autoscale_view`.

In some cases, this can result in different limits being reported. If this is
an issue, consider triggering a draw with `fig.canvas.draw`.

LogLocator.nonsingular now maintains the orders of its arguments
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think everything looks fine in this PR; I'm confused about this and changes to ticker.py though, are they unrelated or do they need to go in tandem with the autoscaling changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They need to go with it; it's all explained in the first message (also the commit message).

````````````````````````````````````````````````````````````````

It no longer reorders them in increasing order. The new behavior is consistent
with MaxNLocator.
54 changes: 26 additions & 28 deletions lib/matplotlib/axes/_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -840,7 +840,7 @@ def axhline(self, y=0, xmin=0, xmax=1, **kwargs):
trans = self.get_yaxis_transform(which='grid')
l = mlines.Line2D([xmin, xmax], [y, y], transform=trans, **kwargs)
self.add_line(l)
self.autoscale_view(scalex=False, scaley=scaley)
self._request_autoscale_view(scalex=False, scaley=scaley)
return l

@docstring.dedent_interpd
Expand Down Expand Up @@ -909,7 +909,7 @@ def axvline(self, x=0, ymin=0, ymax=1, **kwargs):
trans = self.get_xaxis_transform(which='grid')
l = mlines.Line2D([x, x], [ymin, ymax], transform=trans, **kwargs)
self.add_line(l)
self.autoscale_view(scalex=scalex, scaley=False)
self._request_autoscale_view(scalex=scalex, scaley=False)
return l

@docstring.dedent_interpd
Expand Down Expand Up @@ -965,7 +965,7 @@ def axhspan(self, ymin, ymax, xmin=0, xmax=1, **kwargs):
p = mpatches.Polygon(verts, **kwargs)
p.set_transform(trans)
self.add_patch(p)
self.autoscale_view(scalex=False)
self._request_autoscale_view(scalex=False)
return p

def axvspan(self, xmin, xmax, ymin=0, ymax=1, **kwargs):
Expand Down Expand Up @@ -1030,7 +1030,7 @@ def axvspan(self, xmin, xmax, ymin=0, ymax=1, **kwargs):
p = mpatches.Polygon(verts, **kwargs)
p.set_transform(trans)
self.add_patch(p)
self.autoscale_view(scaley=False)
self._request_autoscale_view(scaley=False)
return p

@_preprocess_data(replace_names=["y", "xmin", "xmax", "colors"],
Expand Down Expand Up @@ -1105,7 +1105,7 @@ def hlines(self, y, xmin, xmax, colors='k', linestyles='solid',
corners = (minx, miny), (maxx, maxy)

self.update_datalim(corners)
self.autoscale_view()
self._request_autoscale_view()

return lines

Expand Down Expand Up @@ -1182,7 +1182,7 @@ def vlines(self, x, ymin, ymax, colors='k', linestyles='solid',

corners = (minx, miny), (maxx, maxy)
self.update_datalim(corners)
self.autoscale_view()
self._request_autoscale_view()

return lines

Expand Down Expand Up @@ -1398,7 +1398,7 @@ def eventplot(self, positions, orientation='horizontal', lineoffsets=1,
else: # "horizontal", None or "none" (see EventCollection)
corners = (minpos, minline), (maxpos, maxline)
self.update_datalim(corners)
self.autoscale_view()
self._request_autoscale_view()

return colls

Expand Down Expand Up @@ -1642,7 +1642,7 @@ def plot(self, *args, scalex=True, scaley=True, data=None, **kwargs):
lines = [*self._get_lines(*args, data=data, **kwargs)]
for line in lines:
self.add_line(line)
self.autoscale_view(scalex=scalex, scaley=scaley)
self._request_autoscale_view(scalex=scalex, scaley=scaley)
return lines

@_preprocess_data(replace_names=["x", "y"], label_namer="y")
Expand Down Expand Up @@ -1718,7 +1718,7 @@ def plot_date(self, x, y, fmt='o', tz=None, xdate=True, ydate=False,

ret = self.plot(x, y, fmt, **kwargs)

self.autoscale_view()
self._request_autoscale_view()

return ret

Expand Down Expand Up @@ -2422,7 +2422,7 @@ def bar(self, x, height, width=0.8, bottom=None, *, align="center",
ymin = ymin - np.max(yerr)
ymin = max(ymin * 0.9, 1e-100)
self.dataLim.intervaly = (ymin, ymax)
self.autoscale_view()
self._request_autoscale_view()

bar_container = BarContainer(patches, errorbar, label=label)
self.add_container(bar_container)
Expand Down Expand Up @@ -2623,7 +2623,7 @@ def broken_barh(self, xranges, yrange, **kwargs):

col = mcoll.BrokenBarHCollection(xranges_conv, yrange_conv, **kwargs)
self.add_collection(col, autolim=True)
self.autoscale_view()
self._request_autoscale_view()

return col

Expand Down Expand Up @@ -3429,7 +3429,7 @@ def extract_err(err, data):
for l in caplines:
self.add_line(l)

self.autoscale_view()
self._request_autoscale_view()
errorbar_container = ErrorbarContainer((data_line, tuple(caplines),
tuple(barcols)),
has_xerr=(xerr is not None),
Expand Down Expand Up @@ -4101,7 +4101,7 @@ def dopatch(xs, ys, **kwargs):
axis.set_major_formatter(formatter)
formatter.seq = [*formatter.seq, *datalabels]

self.autoscale_view(
self._request_autoscale_view(
scalex=self._autoscaleXon, scaley=self._autoscaleYon)

return dict(whiskers=whiskers, caps=caps, boxes=boxes,
Expand Down Expand Up @@ -4479,7 +4479,7 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None,
self.set_ymargin(0.05)

self.add_collection(collection)
self.autoscale_view()
self._request_autoscale_view()

return collection

Expand Down Expand Up @@ -4832,9 +4832,7 @@ def hexbin(self, x, y, C=None, gridsize=100, bins=None,

corners = ((xmin, ymin), (xmax, ymax))
self.update_datalim(corners)
collection.sticky_edges.x[:] = [xmin, xmax]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what change caused this to start working.

Copy link
Contributor Author

@anntzer anntzer Mar 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest I don't know either. I do have some other plans to fiddle with hexbin though (but that won't be in this PR).

collection.sticky_edges.y[:] = [ymin, ymax]
self.autoscale_view(tight=True)
self._request_autoscale_view(tight=True)

# add the collection last
self.add_collection(collection, autolim=False)
Expand Down Expand Up @@ -5004,7 +5002,7 @@ def quiver(self, *args, **kw):
q = mquiver.Quiver(self, *args, **kw)

self.add_collection(q, autolim=True)
self.autoscale_view()
self._request_autoscale_view()
return q
quiver.__doc__ = mquiver.Quiver.quiver_doc

Expand All @@ -5020,7 +5018,7 @@ def barbs(self, *args, **kw):

b = mquiver.Barbs(self, *args, **kw)
self.add_collection(b, autolim=True)
self.autoscale_view()
self._request_autoscale_view()
return b

# Uses a custom implementation of data-kwarg handling in
Expand Down Expand Up @@ -5075,7 +5073,7 @@ def fill(self, *args, data=None, **kwargs):
for poly in self._get_patches_for_fill(*args, data=data, **kwargs):
self.add_patch(poly)
patches.append(poly)
self.autoscale_view()
self._request_autoscale_view()
return patches

@_preprocess_data(replace_names=["x", "y1", "y2", "where"])
Expand Down Expand Up @@ -5257,7 +5255,7 @@ def get_interp_point(ind):
self.dataLim.update_from_data_xy(XY2, self.ignore_existing_data_limits,
updatex=False, updatey=True)
self.add_collection(collection, autolim=False)
self.autoscale_view()
self._request_autoscale_view()
return collection

@_preprocess_data(replace_names=["y", "x1", "x2", "where"])
Expand Down Expand Up @@ -5438,7 +5436,7 @@ def get_interp_point(ind):
self.dataLim.update_from_data_xy(X2Y, self.ignore_existing_data_limits,
updatex=True, updatey=False)
self.add_collection(collection, autolim=False)
self.autoscale_view()
self._request_autoscale_view()
return collection

#### plotting z(x,y): imshow, pcolor and relatives, contour
Expand Down Expand Up @@ -5937,7 +5935,7 @@ def pcolor(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
collection.sticky_edges.y[:] = [miny, maxy]
corners = (minx, miny), (maxx, maxy)
self.update_datalim(corners)
self.autoscale_view()
self._request_autoscale_view()
return collection

@_preprocess_data()
Expand Down Expand Up @@ -6150,7 +6148,7 @@ def pcolormesh(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
collection.sticky_edges.y[:] = [miny, maxy]
corners = (minx, miny), (maxx, maxy)
self.update_datalim(corners)
self.autoscale_view()
self._request_autoscale_view()
return collection

@_preprocess_data()
Expand Down Expand Up @@ -6320,22 +6318,22 @@ def pcolorfast(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
ret.sticky_edges.x[:] = [xl, xr]
ret.sticky_edges.y[:] = [yb, yt]
self.update_datalim(np.array([[xl, yb], [xr, yt]]))
self.autoscale_view(tight=True)
self._request_autoscale_view(tight=True)
return ret

@_preprocess_data()
def contour(self, *args, **kwargs):
kwargs['filled'] = False
contours = mcontour.QuadContourSet(self, *args, **kwargs)
self.autoscale_view()
self._request_autoscale_view()
return contours
contour.__doc__ = mcontour.QuadContourSet._contour_doc

@_preprocess_data()
def contourf(self, *args, **kwargs):
kwargs['filled'] = True
contours = mcontour.QuadContourSet(self, *args, **kwargs)
self.autoscale_view()
self._request_autoscale_view()
return contours
contourf.__doc__ = mcontour.QuadContourSet._contour_doc

Expand Down Expand Up @@ -6842,7 +6840,7 @@ def hist(self, x, bins=None, range=None, density=None, weights=None,

self.set_autoscalex_on(_saved_autoscalex)
self.set_autoscaley_on(_saved_autoscaley)
self.autoscale_view()
self._request_autoscale_view()

if label is None:
labels = [None]
Expand Down
Loading