Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc73f4c4

Browse files
committed
Merge SubplotBase into AxesBase.
1 parent9b1fcf6 commitc73f4c4

File tree

27 files changed

+258
-314
lines changed

27 files changed

+258
-314
lines changed

‎doc/api/axes_api.rst

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,6 @@ The Axes class
2727
:no-undoc-members:
2828
:show-inheritance:
2929

30-
31-
Subplots
32-
========
33-
34-
..autosummary::
35-
:toctree: _as_gen
36-
:template: autosummary.rst
37-
:nosignatures:
38-
39-
SubplotBase
40-
subplot_class_factory
41-
4230
Plotting
4331
========
4432

@@ -313,6 +301,7 @@ Axis labels, title, and legend
313301
Axes.get_xlabel
314302
Axes.set_ylabel
315303
Axes.get_ylabel
304+
Axes.label_outer
316305

317306
Axes.set_title
318307
Axes.get_title
@@ -484,6 +473,9 @@ Axes position
484473
Axes.get_axes_locator
485474
Axes.set_axes_locator
486475

476+
Axes.get_subplotspec
477+
Axes.set_subplotspec
478+
487479
Axes.reset_position
488480

489481
Axes.get_position
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
All Axes have ``get_subplotspec`` and ``get_gridspec`` methods now, which returns None for Axes not positioned via a gridspec
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
Previously, this method was only present for Axes positioned via a gridspec.
4+
Following this change, checking ``hasattr(ax, "get_gridspec")`` should now be
5+
replaced by ``ax.get_gridspec() is not None``. For compatibility with older
6+
Matplotlib releases, one can also check
7+
``hasattr(ax, "get_gridspec") and ax.get_gridspec() is not None``.

‎doc/api/prev_api_changes/api_changes_3.3.0/deprecations.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ are deprecated. Panning and zooming are now implemented using the
328328

329329
Passing None to various Axes subclass factories
330330
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
331-
Support for passing ``None`` as base class to `.axes.subplot_class_factory`,
331+
Support for passing ``None`` as base class to ``axes.subplot_class_factory``,
332332
``axes_grid1.parasite_axes.host_axes_class_factory``,
333333
``axes_grid1.parasite_axes.host_subplot_class_factory``,
334334
``axes_grid1.parasite_axes.parasite_axes_class_factory``, and

‎doc/api/prev_api_changes/api_changes_3.4.0/deprecations.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ Subplot-related attributes and methods
3838
Some ``SubplotBase`` methods and attributes have been deprecated and/or moved
3939
to `.SubplotSpec`:
4040

41-
- ``get_geometry`` (use `.SubplotBase.get_subplotspec` instead),
42-
- ``change_geometry`` (use `.SubplotBase.set_subplotspec` instead),
41+
- ``get_geometry`` (use ``SubplotBase.get_subplotspec`` instead),
42+
- ``change_geometry`` (use ``SubplotBase.set_subplotspec`` instead),
4343
- ``is_first_row``, ``is_last_row``, ``is_first_col``, ``is_last_col`` (use the
4444
corresponding methods on the `.SubplotSpec` instance instead),
4545
- ``update_params`` (now a no-op),

‎doc/users/prev_whats_new/whats_new_3.0.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,10 @@ independent on the axes size or units. To revert to the previous behaviour
141141
set the axes' aspect ratio to automatic by using ``ax.set_aspect("auto")`` or
142142
``plt.axis("auto")``.
143143

144-
Add ``ax.get_gridspec`` to `.SubplotBase`
145-
-----------------------------------------
144+
Add ``ax.get_gridspec`` to ``SubplotBase``
145+
------------------------------------------
146146

147-
New method `.SubplotBase.get_gridspec` is added so that users can
147+
New method ``SubplotBase.get_gridspec`` is added so that users can
148148
easily get the gridspec that went into making an axes:
149149

150150
..code::

‎lib/matplotlib/_constrained_layout.py

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,8 @@ def make_layoutgrids(fig, layoutgrids, rect=(0, 0, 1, 1)):
187187

188188
# for each axes at the local level add its gridspec:
189189
foraxinfig._localaxes:
190-
ifhasattr(ax,'get_subplotspec'):
191-
gs=ax.get_subplotspec().get_gridspec()
190+
gs=ax.get_gridspec()
191+
ifgsisnotNone:
192192
layoutgrids=make_layoutgrids_gs(layoutgrids,gs)
193193

194194
returnlayoutgrids
@@ -248,24 +248,22 @@ def check_no_collapsed_axes(layoutgrids, fig):
248248
ok=check_no_collapsed_axes(layoutgrids,sfig)
249249
ifnotok:
250250
returnFalse
251-
252251
foraxinfig.axes:
253-
ifhasattr(ax,'get_subplotspec'):
254-
gs=ax.get_subplotspec().get_gridspec()
255-
ifgsinlayoutgrids:
256-
lg=layoutgrids[gs]
257-
foriinrange(gs.nrows):
258-
forjinrange(gs.ncols):
259-
bb=lg.get_inner_bbox(i,j)
260-
ifbb.width<=0orbb.height<=0:
261-
returnFalse
252+
gs=ax.get_gridspec()
253+
ifgsinlayoutgrids:# also implies gs is not None.
254+
lg=layoutgrids[gs]
255+
foriinrange(gs.nrows):
256+
forjinrange(gs.ncols):
257+
bb=lg.get_inner_bbox(i,j)
258+
ifbb.width<=0orbb.height<=0:
259+
returnFalse
262260
returnTrue
263261

264262

265263
defcompress_fixed_aspect(layoutgrids,fig):
266264
gs=None
267265
foraxinfig.axes:
268-
ifnothasattr(ax,'get_subplotspec'):
266+
ifax.get_subplotspec()isNone:
269267
continue
270268
ax.apply_aspect()
271269
sub=ax.get_subplotspec()
@@ -357,7 +355,7 @@ def make_layout_margins(layoutgrids, fig, renderer, *, w_pad=0, h_pad=0,
357355
layoutgrids[sfig].parent.edit_outer_margin_mins(margins,ss)
358356

359357
foraxinfig._localaxes:
360-
ifnothasattr(ax,'get_subplotspec')ornotax.get_in_layout():
358+
ifnotax.get_subplotspec()ornotax.get_in_layout():
361359
continue
362360

363361
ss=ax.get_subplotspec()
@@ -488,8 +486,8 @@ def match_submerged_margins(layoutgrids, fig):
488486
forsfiginfig.subfigs:
489487
match_submerged_margins(layoutgrids,sfig)
490488

491-
axs= [aforainfig.get_axes()if (hasattr(a,'get_subplotspec')
492-
anda.get_in_layout())]
489+
axs= [aforainfig.get_axes()
490+
ifa.get_subplotspec()isnotNoneanda.get_in_layout()]
493491

494492
forax1inaxs:
495493
ss1=ax1.get_subplotspec()
@@ -620,7 +618,7 @@ def reposition_axes(layoutgrids, fig, renderer, *,
620618
wspace=wspace,hspace=hspace)
621619

622620
foraxinfig._localaxes:
623-
ifnothasattr(ax,'get_subplotspec')ornotax.get_in_layout():
621+
ifax.get_subplotspec()isNoneornotax.get_in_layout():
624622
continue
625623

626624
# grid bbox is in Figure coordinates, but we specify in panel
@@ -742,10 +740,9 @@ def reset_margins(layoutgrids, fig):
742740
forsfiginfig.subfigs:
743741
reset_margins(layoutgrids,sfig)
744742
foraxinfig.axes:
745-
ifhasattr(ax,'get_subplotspec')andax.get_in_layout():
746-
ss=ax.get_subplotspec()
747-
gs=ss.get_gridspec()
748-
ifgsinlayoutgrids:
743+
ifax.get_in_layout():
744+
gs=ax.get_gridspec()
745+
ifgsinlayoutgrids:# also implies gs is not None.
749746
layoutgrids[gs].reset_margins()
750747
layoutgrids[fig].reset_margins()
751748

‎lib/matplotlib/axes/__init__.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,18 @@
1-
from ._subplotsimport*
1+
from .import_base
22
from ._axesimport*
3+
4+
# Backcompat.
5+
from ._axesimportAxesasSubplot
6+
7+
8+
class_SubplotBaseMeta(type):
9+
def__instancecheck__(self,obj):
10+
return (isinstance(obj,_base._AxesBase)
11+
andobj.get_subplotspec()isnotNone)
12+
13+
14+
classSubplotBase(metaclass=_SubplotBaseMeta):
15+
pass
16+
17+
18+
defsubplot_class_factory(cls):returncls

‎lib/matplotlib/axes/_base.py

Lines changed: 119 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
fromcollections.abcimportMutableSequence
1+
fromcollections.abcimportIterable,MutableSequence
22
fromcontextlibimportExitStack
33
importfunctools
44
importinspect
@@ -18,6 +18,7 @@
1818
importmatplotlib.collectionsasmcoll
1919
importmatplotlib.colorsasmcolors
2020
importmatplotlib.font_managerasfont_manager
21+
frommatplotlib.gridspecimportSubplotSpec
2122
importmatplotlib.imageasmimage
2223
importmatplotlib.linesasmlines
2324
importmatplotlib.patchesasmpatches
@@ -569,8 +570,8 @@ def __str__(self):
569570
return"{0}({1[0]:g},{1[1]:g};{1[2]:g}x{1[3]:g})".format(
570571
type(self).__name__,self._position.bounds)
571572

572-
def__init__(self,fig,rect,
573-
*,
573+
def__init__(self,fig,
574+
*args,
574575
facecolor=None,# defaults to rc axes.facecolor
575576
frameon=True,
576577
sharex=None,# use Axes instance's xaxis info
@@ -589,9 +590,18 @@ def __init__(self, fig, rect,
589590
fig : `~matplotlib.figure.Figure`
590591
The Axes is built in the `.Figure` *fig*.
591592
592-
rect : tuple (left, bottom, width, height).
593-
The Axes is built in the rectangle *rect*. *rect* is in
594-
`.Figure` coordinates.
593+
*args
594+
``*args`` can be a single ``(left, bottom, width, height)``
595+
rectangle or a single `.Bbox`. This specifies the rectangle (in
596+
figure coordinates) where the Axes is positioned.
597+
598+
``*args`` can also consist of three numbers or a single three-digit
599+
number; in the latter case, the digits are considered as
600+
independent numbers. The numbers are interpreted as ``(nrows,
601+
ncols, index)``: ``(nrows, ncols)`` specifies the size of an array
602+
of subplots, and ``index`` is the 1-based index of the subplot
603+
being created. Finally, ``*args`` can also directly be a
604+
`.SubplotSpec` instance.
595605
596606
sharex, sharey : `~.axes.Axes`, optional
597607
The x or y `~.matplotlib.axis` is shared with the x or
@@ -616,10 +626,21 @@ def __init__(self, fig, rect,
616626
"""
617627

618628
super().__init__()
619-
ifisinstance(rect,mtransforms.Bbox):
620-
self._position=rect
629+
if"rect"inkwargs:
630+
ifargs:
631+
raiseTypeError(
632+
"'rect' cannot be used together with positional arguments")
633+
rect=kwargs.pop("rect")
634+
_api.check_isinstance((mtransforms.Bbox,Iterable),rect=rect)
635+
args= (rect,)
636+
subplotspec=None
637+
iflen(args)==1andisinstance(args[0],mtransforms.Bbox):
638+
self._position=args[0]
639+
eliflen(args)==1andnp.iterable(args[0]):
640+
self._position=mtransforms.Bbox.from_bounds(*args[0])
621641
else:
622-
self._position=mtransforms.Bbox.from_bounds(*rect)
642+
self._position=self._originalPosition=mtransforms.Bbox.unit()
643+
subplotspec=SubplotSpec._from_subplot_args(fig,args)
623644
ifself._position.width<0orself._position.height<0:
624645
raiseValueError('Width and height specified must be non-negative')
625646
self._originalPosition=self._position.frozen()
@@ -632,8 +653,16 @@ def __init__(self, fig, rect,
632653
self._sharey=sharey
633654
self.set_label(label)
634655
self.set_figure(fig)
656+
# The subplotspec needs to be set after the figure (so that
657+
# figure-level subplotpars are taken into account), but the figure
658+
# needs to be set after self._position is initialized.
659+
ifsubplotspec:
660+
self.set_subplotspec(subplotspec)
661+
else:
662+
self._subplotspec=None
635663
self.set_box_aspect(box_aspect)
636664
self._axes_locator=None# Optionally set via update(kwargs).
665+
637666
# placeholder for any colorbars added that use this Axes.
638667
# (see colorbar.py):
639668
self._colorbars= []
@@ -737,6 +766,19 @@ def __repr__(self):
737766
fields+= [f"{name}label={axis.get_label().get_text()!r}"]
738767
returnf"<{self.__class__.__name__}: "+", ".join(fields)+">"
739768

769+
defget_subplotspec(self):
770+
"""Return the `.SubplotSpec` associated with the subplot, or None."""
771+
returnself._subplotspec
772+
773+
defset_subplotspec(self,subplotspec):
774+
"""Set the `.SubplotSpec`. associated with the subplot."""
775+
self._subplotspec=subplotspec
776+
self._set_position(subplotspec.get_position(self.figure))
777+
778+
defget_gridspec(self):
779+
"""Return the `.GridSpec` associated with the subplot, or None."""
780+
returnself._subplotspec.get_gridspec()ifself._subplotspecelseNone
781+
740782
@_api.delete_parameter("3.6","args")
741783
@_api.delete_parameter("3.6","kwargs")
742784
defget_window_extent(self,renderer=None,*args,**kwargs):
@@ -4424,17 +4466,23 @@ def get_tightbbox(self, renderer=None, call_axes_locator=True,
44244466

44254467
def_make_twin_axes(self,*args,**kwargs):
44264468
"""Make a twinx Axes of self. This is used for twinx and twiny."""
4427-
# Typically, SubplotBase._make_twin_axes is called instead of this.
44284469
if'sharex'inkwargsand'sharey'inkwargs:
4429-
raiseValueError("Twinned Axes may share only one axis")
4430-
ax2=self.figure.add_axes(
4431-
self.get_position(True),*args,**kwargs,
4432-
axes_locator=_TransformedBoundsLocator(
4433-
[0,0,1,1],self.transAxes))
4470+
# The following line is added in v2.2 to avoid breaking Seaborn,
4471+
# which currently uses this internal API.
4472+
ifkwargs["sharex"]isnotselfandkwargs["sharey"]isnotself:
4473+
raiseValueError("Twinned Axes may share only one axis")
4474+
ss=self.get_subplotspec()
4475+
ifss:
4476+
twin=self.figure.add_subplot(ss,*args,**kwargs)
4477+
else:
4478+
twin=self.figure.add_axes(
4479+
self.get_position(True),*args,**kwargs,
4480+
axes_locator=_TransformedBoundsLocator(
4481+
[0,0,1,1],self.transAxes))
44344482
self.set_adjustable('datalim')
4435-
ax2.set_adjustable('datalim')
4436-
self._twinned_axes.join(self,ax2)
4437-
returnax2
4483+
twin.set_adjustable('datalim')
4484+
self._twinned_axes.join(self,twin)
4485+
returntwin
44384486

44394487
deftwinx(self):
44404488
"""
@@ -4502,3 +4550,56 @@ def get_shared_x_axes(self):
45024550
defget_shared_y_axes(self):
45034551
"""Return an immutable view on the shared y-axes Grouper."""
45044552
returncbook.GrouperView(self._shared_axes["y"])
4553+
4554+
deflabel_outer(self):
4555+
"""
4556+
Only show "outer" labels and tick labels.
4557+
4558+
x-labels are only kept for subplots on the last row (or first row, if
4559+
labels are on the top side); y-labels only for subplots on the first
4560+
column (or last column, if labels are on the right side).
4561+
"""
4562+
self._label_outer_xaxis(check_patch=False)
4563+
self._label_outer_yaxis(check_patch=False)
4564+
4565+
def_label_outer_xaxis(self,*,check_patch):
4566+
# see documentation in label_outer.
4567+
ifcheck_patchandnotisinstance(self.patch,mpl.patches.Rectangle):
4568+
return
4569+
ss=self.get_subplotspec()
4570+
ifnotss:
4571+
return
4572+
label_position=self.xaxis.get_label_position()
4573+
ifnotss.is_first_row():# Remove top label/ticklabels/offsettext.
4574+
iflabel_position=="top":
4575+
self.set_xlabel("")
4576+
self.xaxis.set_tick_params(which="both",labeltop=False)
4577+
ifself.xaxis.offsetText.get_position()[1]==1:
4578+
self.xaxis.offsetText.set_visible(False)
4579+
ifnotss.is_last_row():# Remove bottom label/ticklabels/offsettext.
4580+
iflabel_position=="bottom":
4581+
self.set_xlabel("")
4582+
self.xaxis.set_tick_params(which="both",labelbottom=False)
4583+
ifself.xaxis.offsetText.get_position()[1]==0:
4584+
self.xaxis.offsetText.set_visible(False)
4585+
4586+
def_label_outer_yaxis(self,*,check_patch):
4587+
# see documentation in label_outer.
4588+
ifcheck_patchandnotisinstance(self.patch,mpl.patches.Rectangle):
4589+
return
4590+
ss=self.get_subplotspec()
4591+
ifnotss:
4592+
return
4593+
label_position=self.yaxis.get_label_position()
4594+
ifnotss.is_first_col():# Remove left label/ticklabels/offsettext.
4595+
iflabel_position=="left":
4596+
self.set_ylabel("")
4597+
self.yaxis.set_tick_params(which="both",labelleft=False)
4598+
ifself.yaxis.offsetText.get_position()[0]==0:
4599+
self.yaxis.offsetText.set_visible(False)
4600+
ifnotss.is_last_col():# Remove right label/ticklabels/offsettext.
4601+
iflabel_position=="right":
4602+
self.set_ylabel("")
4603+
self.yaxis.set_tick_params(which="both",labelright=False)
4604+
ifself.yaxis.offsetText.get_position()[0]==1:
4605+
self.yaxis.offsetText.set_visible(False)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp