Skip to content

Commit a080a71

Browse files
committed
ENH: ax.add_collection(..., autolim=True) updates view limits
This makes explicit calls to `autoscale_view()` or `_request_autoscale_view()` unnecessary. 3D Axes have a special `auto_scale_xyz()`, also there's a mixture of `add_collection()` and `add_collection3d()`. This needs separate sorting . I've added a private value `autolim="_datalim_only"` to keep the behavior for 3D Axes unchanged for now. That will be resolved by a follow-up PR. I believe it's getting too complicated if we fold this into the 2D change.
1 parent 011d12f commit a080a71

File tree

16 files changed

+57
-36
lines changed

16 files changed

+57
-36
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
``Axes.add_collection(..., autolim=True)`` updates view limits
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
``Axes.add_collection(..., autolim=True)`` has so far only updated the data limits.
5+
Users needed to additionally call `.Axes.autoscale_view` to update the view limits.
6+
View limits are now updated as well if ``autolim=True``, using a lazy internal
7+
update mechanism, so that the costs only apply once also if you add multiple
8+
collections.

galleries/examples/shapes_and_collections/collections.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,12 @@
5959
# but it is good enough to generate a plot that you can use
6060
# as a starting point. If you know beforehand the range of
6161
# x and y that you want to show, it is better to set them
62-
# explicitly, leave out the *autolim* keyword argument (or set it to False),
63-
# and omit the 'ax1.autoscale_view()' call below.
62+
# explicitly, set the *autolim* keyword argument to False.
6463

6564
# Make a transform for the line segments such that their size is
6665
# given in points:
6766
col.set_color(colors)
6867

69-
ax1.autoscale_view() # See comment above, after ax1.add_collection.
7068
ax1.set_title('LineCollection using offsets')
7169

7270

@@ -79,7 +77,6 @@
7977
col.set_color(colors)
8078

8179

82-
ax2.autoscale_view()
8380
ax2.set_title('PolyCollection using offsets')
8481

8582
# 7-sided regular polygons
@@ -90,7 +87,6 @@
9087
col.set_transform(trans) # the points to pixels transform
9188
ax3.add_collection(col, autolim=True)
9289
col.set_color(colors)
93-
ax3.autoscale_view()
9490
ax3.set_title('RegularPolyCollection using offsets')
9591

9692

@@ -114,7 +110,6 @@
114110
col = collections.LineCollection(segs, offsets=offs)
115111
ax4.add_collection(col, autolim=True)
116112
col.set_color(colors)
117-
ax4.autoscale_view()
118113
ax4.set_title('Successive data offsets')
119114
ax4.set_xlabel('Zonal velocity component (m/s)')
120115
ax4.set_ylabel('Depth (m)')

galleries/examples/shapes_and_collections/ellipse_collection.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
offset_transform=ax.transData)
3131
ec.set_array((X + Y).ravel())
3232
ax.add_collection(ec)
33-
ax.autoscale_view()
3433
ax.set_xlabel('X')
3534
ax.set_ylabel('y')
3635
cbar = plt.colorbar(ec)

galleries/users_explain/axes/autoscale.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,4 +177,3 @@
177177
offset_transform=ax.transData, # Propagate transformations of the Axes
178178
)
179179
ax.add_collection(collection)
180-
ax.autoscale_view()

lib/matplotlib/axes/_axes.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3028,7 +3028,6 @@ def broken_barh(self, xranges, yrange, **kwargs):
30283028

30293029
col = mcoll.PolyCollection(np.array(vertices), **kwargs)
30303030
self.add_collection(col, autolim=True)
3031-
self._request_autoscale_view()
30323031

30333032
return col
30343033

@@ -5337,7 +5336,6 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None,
53375336
self.set_ymargin(0.05)
53385337

53395338
self.add_collection(collection)
5340-
self._request_autoscale_view()
53415339

53425340
return collection
53435341

@@ -5808,7 +5806,6 @@ def quiver(self, *args, **kwargs):
58085806
args = self._quiver_units(args, kwargs)
58095807
q = mquiver.Quiver(self, *args, **kwargs)
58105808
self.add_collection(q, autolim=True)
5811-
self._request_autoscale_view()
58125809
return q
58135810

58145811
# args can be some combination of X, Y, U, V, C and all should be replaced
@@ -5820,7 +5817,6 @@ def barbs(self, *args, **kwargs):
58205817
args = self._quiver_units(args, kwargs)
58215818
b = mquiver.Barbs(self, *args, **kwargs)
58225819
self.add_collection(b, autolim=True)
5823-
self._request_autoscale_view()
58245820
return b
58255821

58265822
# Uses a custom implementation of data-kwarg handling in
@@ -5980,7 +5976,6 @@ def _fill_between_x_or_y(
59805976
where=where, interpolate=interpolate, step=step, **kwargs)
59815977

59825978
self.add_collection(collection)
5983-
self._request_autoscale_view()
59845979
return collection
59855980

59865981
def _fill_between_process_units(self, ind_dir, dep_dir, ind, dep1, dep2, **kwargs):

lib/matplotlib/axes/_base.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2336,6 +2336,23 @@ def add_child_axes(self, ax):
23362336
def add_collection(self, collection, autolim=True):
23372337
"""
23382338
Add a `.Collection` to the Axes; return the collection.
2339+
2340+
Parameters
2341+
----------
2342+
collection : `.Collection`
2343+
The collection to add.
2344+
autolim : bool
2345+
Whether to update data and view limits.
2346+
2347+
.. versionchanged:: 3.11
2348+
2349+
This now also updates the view limits, making explicit
2350+
calls to `~.Axes.autoscale_view` unnecessary.
2351+
2352+
As an implementation detail, the value "_datalim_only" is
2353+
supported to smooth the internal transition from pre-3.11
2354+
behavior. This is not a public interface and will be removed
2355+
again in the future.
23392356
"""
23402357
_api.check_isinstance(mcoll.Collection, collection=collection)
23412358
if not collection.get_label():
@@ -2371,6 +2388,8 @@ def add_collection(self, collection, autolim=True):
23712388
updatex=x_is_data or ox_is_data,
23722389
updatey=y_is_data or oy_is_data,
23732390
)
2391+
if autolim != "_datalim_only":
2392+
self._request_autoscale_view()
23742393

23752394
self.stale = True
23762395
return collection

lib/matplotlib/axes/_base.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ class _AxesBase(martist.Artist):
234234
def add_artist(self, a: Artist) -> Artist: ...
235235
def add_child_axes(self, ax: _AxesBase) -> _AxesBase: ...
236236
def add_collection(
237-
self, collection: Collection, autolim: bool = ...
237+
self, collection: Collection, autolim: bool | Literal["_datalim_only"] = ...
238238
) -> Collection: ...
239239
def add_image(self, image: AxesImage) -> AxesImage: ...
240240
def add_line(self, line: Line2D) -> Line2D: ...

lib/matplotlib/colorbar.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ def __init__(
373373
colors=[mpl.rcParams['axes.edgecolor']],
374374
linewidths=[0.5 * mpl.rcParams['axes.linewidth']],
375375
clip_on=False)
376-
self.ax.add_collection(self.dividers)
376+
self.ax.add_collection(self.dividers, autolim=False)
377377

378378
self._locator = None
379379
self._minorlocator = None
@@ -807,7 +807,7 @@ def add_lines(self, *args, **kwargs):
807807
xy = self.ax.transAxes.inverted().transform(inches.transform(xy))
808808
col.set_clip_path(mpath.Path(xy, closed=True),
809809
self.ax.transAxes)
810-
self.ax.add_collection(col)
810+
self.ax.add_collection(col, autolim=False)
811811
self.stale = True
812812

813813
def update_ticks(self):

lib/matplotlib/tests/test_backend_ps.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,11 @@ def test_path_collection():
354354
sizes = [0.02, 0.04]
355355
pc = mcollections.PathCollection(paths, sizes, zorder=-1,
356356
facecolors='yellow', offsets=offsets)
357-
ax.add_collection(pc)
357+
# Note: autolim=False is used to keep the view limits as is for now,
358+
# given the updated behavior of autolim=True to also update the view
359+
# limits. It may be reasonable to test the limits handling in the future
360+
# as well. This will require regenerating the reference image.
361+
ax.add_collection(pc, autolim=False)
358362
ax.set_xlim(0, 1)
359363

360364

lib/matplotlib/tests/test_collections.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,6 @@ def test_EllipseCollection():
408408
ww, hh, aa, units='x', offsets=XY, offset_transform=ax.transData,
409409
facecolors='none')
410410
ax.add_collection(ec)
411-
ax.autoscale_view()
412411

413412

414413
def test_EllipseCollection_setter_getter():
@@ -526,7 +525,6 @@ def test_regularpolycollection_rotate():
526525
4, sizes=(100,), rotation=alpha,
527526
offsets=[xy], offset_transform=ax.transData)
528527
ax.add_collection(col, autolim=True)
529-
ax.autoscale_view()
530528

531529

532530
@image_comparison(['regularpolycollection_scale.png'], remove_text=True)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy