Skip to content

Commit 5173cda

Browse files
authored
Merge pull request #18564 from anntzer/ss
MNT: Prepare for merging SubplotBase into AxesBase.
2 parents 6aca58e + 261f706 commit 5173cda

File tree

14 files changed

+93
-35
lines changed

14 files changed

+93
-35
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Axes3D no longer adds itself to figure
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
New `.Axes3D` objects previously added themselves to figures when they were
5+
created, which lead to them being added twice if
6+
``fig.add_subplot(111, projection='3d')`` was called. Now ``ax = Axes3d(fig)``
7+
will need to be explicitly added to the figure with ``fig.add_axes(ax)``, as
8+
also needs to be done for normal `.axes.Axes`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Subplot-related attributes and methods
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
Some ``SubplotBase`` attributes have been deprecated and/or moved to
4+
`.SubplotSpec`: ``get_geometry`` (use `.SubplotBase.get_subplotspec`
5+
instead), ``change_geometry`` (use `.SubplotBase.set_subplotspec` instead),
6+
``is_first_row``, ``is_last_row``, ``is_first_col``, ``is_last_col`` (use the
7+
corresponding methods on the `.SubplotSpec` instance instead), ``figbox`` (use
8+
``ax.get_subplotspec().get_geometry(ax.figure)`` instead to recompute the
9+
geometry, or ``ax.get_position()`` to read its current value), ``numRows``,
10+
``numCols`` (use the ``nrows`` and ``ncols`` attribute on the `.GridSpec`
11+
instead).
12+
13+
Axes constructor
14+
~~~~~~~~~~~~~~~~
15+
Parameters of the Axes constructor other than *fig* and *rect* will become
16+
keyword-only in a future version.

examples/userdemo/demo_gridspec06.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ def squiggle_xy(a, b, c, d):
2929

3030
# show only the outside spines
3131
for ax in fig.get_axes():
32-
ax.spines['top'].set_visible(ax.is_first_row())
33-
ax.spines['bottom'].set_visible(ax.is_last_row())
34-
ax.spines['left'].set_visible(ax.is_first_col())
35-
ax.spines['right'].set_visible(ax.is_last_col())
32+
ss = ax.get_subplotspec()
33+
ax.spines['top'].set_visible(ss.is_first_row())
34+
ax.spines['bottom'].set_visible(ss.is_last_row())
35+
ax.spines['left'].set_visible(ss.is_first_col())
36+
ax.spines['right'].set_visible(ss.is_last_col())
3637

3738
plt.show()

lib/matplotlib/axes/_base.py

+1
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ def __str__(self):
460460
return "{0}({1[0]:g},{1[1]:g};{1[2]:g}x{1[3]:g})".format(
461461
type(self).__name__, self._position.bounds)
462462

463+
@cbook._make_keyword_only("3.4", "facecolor")
463464
def __init__(self, fig, rect,
464465
facecolor=None, # defaults to rc axes.facecolor
465466
frameon=True,

lib/matplotlib/axes/_subplots.py

+34-11
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,10 @@ def __init__(self, fig, *args, **kwargs):
3333
**kwargs
3434
Keyword arguments are passed to the Axes (sub)class constructor.
3535
"""
36-
37-
self.figure = fig
38-
self._subplotspec = SubplotSpec._from_subplot_args(fig, args)
39-
self.update_params()
4036
# _axes_class is set in the subplot_class_factory
41-
self._axes_class.__init__(self, fig, self.figbox, **kwargs)
37+
self._axes_class.__init__(self, fig, [0, 0, 1, 1], **kwargs)
38+
# This will also update the axes position.
39+
self.set_subplotspec(SubplotSpec._from_subplot_args(fig, args))
4240

4341
def __reduce__(self):
4442
# get the first axes class which does not inherit from a subplotbase
@@ -49,12 +47,15 @@ def __reduce__(self):
4947
(axes_class,),
5048
self.__getstate__())
5149

50+
@cbook.deprecated(
51+
"3.4", alternative="get_subplotspec",
52+
addendum="(get_subplotspec returns a SubplotSpec instance.)")
5253
def get_geometry(self):
5354
"""Get the subplot geometry, e.g., (2, 2, 3)."""
5455
rows, cols, num1, num2 = self.get_subplotspec().get_geometry()
5556
return rows, cols, num1 + 1 # for compatibility
5657

57-
# COVERAGE NOTE: Never used internally or from examples
58+
@cbook.deprecated("3.4", alternative="set_subplotspec")
5859
def change_geometry(self, numrows, numcols, num):
5960
"""Change subplot geometry, e.g., from (1, 1, 1) to (2, 2, 3)."""
6061
self._subplotspec = GridSpec(numrows, numcols,
@@ -69,16 +70,33 @@ def get_subplotspec(self):
6970
def set_subplotspec(self, subplotspec):
7071
"""Set the `.SubplotSpec`. instance associated with the subplot."""
7172
self._subplotspec = subplotspec
73+
self._set_position(subplotspec.get_position(self.figure))
7274

7375
def get_gridspec(self):
7476
"""Return the `.GridSpec` instance associated with the subplot."""
7577
return self._subplotspec.get_gridspec()
7678

79+
@cbook.deprecated(
80+
"3.4", alternative="get_subplotspec().get_position(self.figure)")
81+
@property
82+
def figbox(self):
83+
return self.get_subplotspec().get_position(self.figure)
84+
85+
@cbook.deprecated("3.4", alternative="get_gridspec().nrows")
86+
@property
87+
def numRows(self):
88+
return self.get_gridspec().nrows
89+
90+
@cbook.deprecated("3.4", alternative="get_gridspec().ncols")
91+
@property
92+
def numCols(self):
93+
return self.get_gridspec().ncols
94+
95+
@cbook.deprecated("3.4")
7796
def update_params(self):
7897
"""Update the subplot position from ``self.figure.subplotpars``."""
79-
self.figbox, _, _, self.numRows, self.numCols = \
80-
self.get_subplotspec().get_position(self.figure,
81-
return_all=True)
98+
# Now a no-op, as figbox/numRows/numCols are (deprecated) auto-updating
99+
# properties.
82100

83101
@cbook.deprecated("3.2", alternative="ax.get_subplotspec().rowspan.start")
84102
@property
@@ -90,15 +108,19 @@ def rowNum(self):
90108
def colNum(self):
91109
return self.get_subplotspec().colspan.start
92110

111+
@cbook.deprecated("3.4", alternative="ax.get_subplotspec().is_first_row()")
93112
def is_first_row(self):
94113
return self.get_subplotspec().rowspan.start == 0
95114

115+
@cbook.deprecated("3.4", alternative="ax.get_subplotspec().is_last_row()")
96116
def is_last_row(self):
97117
return self.get_subplotspec().rowspan.stop == self.get_gridspec().nrows
98118

119+
@cbook.deprecated("3.4", alternative="ax.get_subplotspec().is_first_col()")
99120
def is_first_col(self):
100121
return self.get_subplotspec().colspan.start == 0
101122

123+
@cbook.deprecated("3.4", alternative="ax.get_subplotspec().is_last_col()")
102124
def is_last_col(self):
103125
return self.get_subplotspec().colspan.stop == self.get_gridspec().ncols
104126

@@ -109,8 +131,9 @@ def label_outer(self):
109131
x-labels are only kept for subplots on the last row; y-labels only for
110132
subplots on the first column.
111133
"""
112-
lastrow = self.is_last_row()
113-
firstcol = self.is_first_col()
134+
ss = self.get_subplotspec()
135+
lastrow = ss.is_last_row()
136+
firstcol = ss.is_first_col()
114137
if not lastrow:
115138
for label in self.get_xticklabels(which="both"):
116139
label.set_visible(False)

lib/matplotlib/colorbar.py

-2
Original file line numberDiff line numberDiff line change
@@ -1540,8 +1540,6 @@ def make_axes_gridspec(parent, *, location=None, orientation=None,
15401540
aspect = 1 / aspect
15411541

15421542
parent.set_subplotspec(ss_main)
1543-
parent.update_params()
1544-
parent._set_position(parent.figbox)
15451543
parent.set_anchor(loc_settings["panchor"])
15461544

15471545
fig = parent.get_figure()

lib/matplotlib/figure.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -607,15 +607,15 @@ def autofmt_xdate(
607607
"3.3", message="Support for passing which=None to mean "
608608
"which='major' is deprecated since %(since)s and will be "
609609
"removed %(removal)s.")
610-
allsubplots = all(hasattr(ax, 'is_last_row') for ax in self.axes)
610+
allsubplots = all(hasattr(ax, 'get_subplotspec') for ax in self.axes)
611611
if len(self.axes) == 1:
612612
for label in self.axes[0].get_xticklabels(which=which):
613613
label.set_ha(ha)
614614
label.set_rotation(rotation)
615615
else:
616616
if allsubplots:
617617
for ax in self.get_axes():
618-
if ax.is_last_row():
618+
if ax.get_subplotspec().is_last_row():
619619
for label in ax.get_xticklabels(which=which):
620620
label.set_ha(ha)
621621
label.set_rotation(rotation)
@@ -2420,8 +2420,7 @@ def subplots_adjust(self, left=None, bottom=None, right=None, top=None,
24202420
self.subplotpars.update(left, bottom, right, top, wspace, hspace)
24212421
for ax in self.axes:
24222422
if isinstance(ax, SubplotBase):
2423-
ax.update_params()
2424-
ax.set_position(ax.figbox)
2423+
ax._set_position(ax.get_subplotspec().get_position(self))
24252424
self.stale = True
24262425

24272426
def ginput(self, n=1, timeout=30, show_clicks=True,

lib/matplotlib/gridspec.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -489,8 +489,8 @@ def update(self, **kwargs):
489489
if isinstance(ax, mpl.axes.SubplotBase):
490490
ss = ax.get_subplotspec().get_topmost_subplotspec()
491491
if ss.get_gridspec() == self:
492-
ax.update_params()
493-
ax._set_position(ax.figbox)
492+
ax._set_position(
493+
ax.get_subplotspec().get_position(ax.figure))
494494

495495
def get_subplot_params(self, figure=None):
496496
"""
@@ -764,6 +764,19 @@ def colspan(self):
764764
c1, c2 = sorted([self.num1 % ncols, self.num2 % ncols])
765765
return range(c1, c2 + 1)
766766

767+
def is_first_row(self):
768+
return self.rowspan.start == 0
769+
770+
def is_last_row(self):
771+
return self.rowspan.stop == self.get_gridspec().nrows
772+
773+
def is_first_col(self):
774+
return self.colspan.start == 0
775+
776+
def is_last_col(self):
777+
return self.colspan.stop == self.get_gridspec().ncols
778+
779+
@cbook._delete_parameter("3.4", "return_all")
767780
def get_position(self, figure, return_all=False):
768781
"""
769782
Update the subplot position from ``figure.subplotpars``.

lib/matplotlib/tests/test_collections.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ def test_polycollection_close():
365365
[[3., 0.], [3., 1.], [4., 1.], [4., 0.]]]
366366

367367
fig = plt.figure()
368-
ax = Axes3D(fig)
368+
ax = fig.add_axes(Axes3D(fig))
369369

370370
colors = ['r', 'g', 'b', 'y', 'k']
371371
zpos = list(range(5))

lib/matplotlib/tests/test_colorbar.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,13 @@ def test_remove_from_figure(use_gridspec):
224224
fig, ax = plt.subplots()
225225
sc = ax.scatter([1, 2], [3, 4], cmap="spring")
226226
sc.set_array(np.array([5, 6]))
227-
pre_figbox = np.array(ax.figbox)
227+
pre_position = ax.get_position()
228228
cb = fig.colorbar(sc, use_gridspec=use_gridspec)
229229
fig.subplots_adjust()
230230
cb.remove()
231231
fig.subplots_adjust()
232-
post_figbox = np.array(ax.figbox)
233-
assert (pre_figbox == post_figbox).all()
232+
post_position = ax.get_position()
233+
assert (pre_position.get_points() == post_position.get_points()).all()
234234

235235

236236
def test_colorbarbase():

lib/matplotlib/tests/test_figure.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ def test_gca():
170170
# Changing the projection will throw a warning
171171
assert fig.gca(polar=True) is not ax3
172172
assert fig.gca(polar=True) is not ax2
173-
assert fig.gca().get_geometry() == (1, 1, 1)
173+
assert fig.gca().get_subplotspec().get_geometry() == (1, 1, 0, 0)
174174

175175
fig.sca(ax1)
176176
assert fig.gca(projection='rectilinear') is ax1

lib/mpl_toolkits/mplot3d/axes3d.py

-2
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,6 @@ def __init__(
131131
pseudo_bbox = self.transLimits.inverted().transform([(0, 0), (1, 1)])
132132
self._pseudo_w, self._pseudo_h = pseudo_bbox[1] - pseudo_bbox[0]
133133

134-
self.figure.add_axes(self)
135-
136134
# mplot3d currently manages its own spines and needs these turned off
137135
# for bounding box calculations
138136
for k in self.spines.keys():

lib/mpl_toolkits/tests/test_mplot3d.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ def test_add_collection3d_zs_scalar():
700700
@mpl3d_image_comparison(['axes3d_labelpad.png'], remove_text=False)
701701
def test_axes3d_labelpad():
702702
fig = plt.figure()
703-
ax = Axes3D(fig)
703+
ax = fig.add_axes(Axes3D(fig))
704704
# labelpad respects rcParams
705705
assert ax.xaxis.labelpad == mpl.rcParams['axes.labelpad']
706706
# labelpad can be set in set_label

tutorials/intermediate/gridspec.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -246,10 +246,11 @@ def squiggle_xy(a, b, c, d, i=np.arange(0.0, 2*np.pi, 0.05)):
246246

247247
# show only the outside spines
248248
for ax in fig11.get_axes():
249-
ax.spines['top'].set_visible(ax.is_first_row())
250-
ax.spines['bottom'].set_visible(ax.is_last_row())
251-
ax.spines['left'].set_visible(ax.is_first_col())
252-
ax.spines['right'].set_visible(ax.is_last_col())
249+
ss = ax.get_subplotspec()
250+
ax.spines['top'].set_visible(ss.is_first_row())
251+
ax.spines['bottom'].set_visible(ss.is_last_row())
252+
ax.spines['left'].set_visible(ss.is_first_col())
253+
ax.spines['right'].set_visible(ss.is_last_col())
253254

254255
plt.show()
255256

0 commit comments

Comments
 (0)