Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9085810

Browse files
authored
Merge pull request #15287 from anntzer/lateshare
Allow sharex/y after axes creation.
2 parents ce42e8e + 83c2d7b commit 9085810

File tree

4 files changed

+80
-31
lines changed

4 files changed

+80
-31
lines changed

doc/api/axes_api.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,8 +447,8 @@ Adding Artists
447447
Axes.add_table
448448

449449

450-
Twinning
451-
========
450+
Twinning and sharing
451+
====================
452452

453453
.. autosummary::
454454
:toctree: _as_gen
@@ -458,6 +458,9 @@ Twinning
458458
Axes.twinx
459459
Axes.twiny
460460

461+
Axes.sharex
462+
Axes.sharey
463+
461464
Axes.get_shared_x_axes
462465
Axes.get_shared_y_axes
463466

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
`.Axes.sharex`, `.Axes.sharey`
2+
------------------------------
3+
These new methods allow sharing axes *immediately* after creating them. For
4+
example, they can be used to selectively link some axes created all together
5+
using `~.Figure.subplots`.
6+
7+
Note that they may *not* be used to share axes after any operation (e.g.,
8+
drawing) has occurred on them.

examples/subplots_axes_and_figures/subplots_demo.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,23 @@
176176
for ax in axs.flat:
177177
ax.label_outer()
178178

179+
###############################################################################
180+
# If you want a more complex sharing structure, you can first create the
181+
# grid of axes with no sharing, and then call `.axes.Axes.sharex` or
182+
# `.axes.Axes.sharey` to add sharing info a posteriori.
183+
184+
fig, axs = plt.subplots(2, 2)
185+
axs[0, 0].plot(x, y)
186+
axs[0, 0].set_title("main")
187+
axs[1, 0].plot(x, y**2)
188+
axs[1, 0].set_title("shares x with main")
189+
axs[1, 0].sharex(axs[0, 0])
190+
axs[0, 1].plot(x + 1, y + 1)
191+
axs[0, 1].set_title("unrelated")
192+
axs[1, 1].plot(x + 2, y + 2)
193+
axs[1, 1].set_title("also unrelated")
194+
fig.tight_layout()
195+
179196
###############################################################################
180197
# Polar axes
181198
# """"""""""

lib/matplotlib/axes/_base.py

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -487,16 +487,8 @@ def __init__(self, fig, rect,
487487
self._anchor = 'C'
488488
self._stale_viewlim_x = False
489489
self._stale_viewlim_y = False
490-
self._sharex = sharex
491-
self._sharey = sharey
492-
if sharex is not None:
493-
if not isinstance(sharex, _AxesBase):
494-
raise TypeError('sharex must be an axes, not a bool')
495-
self._shared_x_axes.join(self, sharex)
496-
if sharey is not None:
497-
if not isinstance(sharey, _AxesBase):
498-
raise TypeError('sharey must be an axes, not a bool')
499-
self._shared_y_axes.join(self, sharey)
490+
self._sharex = None
491+
self._sharey = None
500492
self.set_label(label)
501493
self.set_figure(fig)
502494
self.set_box_aspect(box_aspect)
@@ -515,6 +507,11 @@ def __init__(self, fig, rect,
515507
self._rasterization_zorder = None
516508
self.cla()
517509

510+
if sharex is not None:
511+
self.sharex(sharex)
512+
if sharey is not None:
513+
self.sharey(sharey)
514+
518515
# funcs used to format x and y - fall back on major formatters
519516
self.fmt_xdata = None
520517
self.fmt_ydata = None
@@ -1008,6 +1005,44 @@ def _gen_axes_spines(self, locations=None, offset=0.0, units='inches'):
10081005
return OrderedDict((side, mspines.Spine.linear_spine(self, side))
10091006
for side in ['left', 'right', 'bottom', 'top'])
10101007

1008+
def sharex(self, other):
1009+
"""
1010+
Share the x-axis with *other*.
1011+
1012+
This is equivalent to passing ``sharex=other`` when constructing the
1013+
axes, and cannot be used if the x-axis is already being shared with
1014+
another axes.
1015+
"""
1016+
cbook._check_isinstance(_AxesBase, other=other)
1017+
if self._sharex is not None and other is not self._sharex:
1018+
raise ValueError("x-axis is already shared")
1019+
self._shared_x_axes.join(self, other)
1020+
self._sharex = other
1021+
self.xaxis.major = other.xaxis.major # Ticker instances holding
1022+
self.xaxis.minor = other.xaxis.minor # locator and formatter.
1023+
x0, x1 = other.get_xlim()
1024+
self.set_xlim(x0, x1, emit=False, auto=other.get_autoscalex_on())
1025+
self.xaxis._scale = other.xaxis._scale
1026+
1027+
def sharey(self, other):
1028+
"""
1029+
Share the y-axis with *other*.
1030+
1031+
This is equivalent to passing ``sharey=other`` when constructing the
1032+
axes, and cannot be used if the y-axis is already being shared with
1033+
another axes.
1034+
"""
1035+
cbook._check_isinstance(_AxesBase, other=other)
1036+
if self._sharey is not None and other is not self._sharey:
1037+
raise ValueError("y-axis is already shared")
1038+
self._shared_y_axes.join(self, other)
1039+
self._sharey = other
1040+
self.yaxis.major = other.yaxis.major # Ticker instances holding
1041+
self.yaxis.minor = other.yaxis.minor # locator and formatter.
1042+
y0, y1 = other.get_ylim()
1043+
self.set_ylim(y0, y1, emit=False, auto=other.get_autoscaley_on())
1044+
self.yaxis._scale = other.yaxis._scale
1045+
10111046
def cla(self):
10121047
"""Clear the current axes."""
10131048
# Note: this is called by Axes.__init__()
@@ -1031,38 +1066,25 @@ def cla(self):
10311066
self.callbacks = cbook.CallbackRegistry()
10321067

10331068
if self._sharex is not None:
1034-
# major and minor are axis.Ticker class instances with
1035-
# locator and formatter attributes
1036-
self.xaxis.major = self._sharex.xaxis.major
1037-
self.xaxis.minor = self._sharex.xaxis.minor
1038-
x0, x1 = self._sharex.get_xlim()
1039-
self.set_xlim(x0, x1, emit=False,
1040-
auto=self._sharex.get_autoscalex_on())
1041-
self.xaxis._scale = self._sharex.xaxis._scale
1069+
self.sharex(self._sharex)
10421070
else:
10431071
self.xaxis._set_scale('linear')
10441072
try:
10451073
self.set_xlim(0, 1)
10461074
except TypeError:
10471075
pass
1048-
10491076
if self._sharey is not None:
1050-
self.yaxis.major = self._sharey.yaxis.major
1051-
self.yaxis.minor = self._sharey.yaxis.minor
1052-
y0, y1 = self._sharey.get_ylim()
1053-
self.set_ylim(y0, y1, emit=False,
1054-
auto=self._sharey.get_autoscaley_on())
1055-
self.yaxis._scale = self._sharey.yaxis._scale
1077+
self.sharey(self._sharey)
10561078
else:
10571079
self.yaxis._set_scale('linear')
10581080
try:
10591081
self.set_ylim(0, 1)
10601082
except TypeError:
10611083
pass
1084+
10621085
# update the minor locator for x and y axis based on rcParams
10631086
if mpl.rcParams['xtick.minor.visible']:
10641087
self.xaxis.set_minor_locator(mticker.AutoMinorLocator())
1065-
10661088
if mpl.rcParams['ytick.minor.visible']:
10671089
self.yaxis.set_minor_locator(mticker.AutoMinorLocator())
10681090

@@ -1144,11 +1166,10 @@ def cla(self):
11441166

11451167
self._shared_x_axes.clean()
11461168
self._shared_y_axes.clean()
1147-
if self._sharex:
1169+
if self._sharex is not None:
11481170
self.xaxis.set_visible(xaxis_visible)
11491171
self.patch.set_visible(patch_visible)
1150-
1151-
if self._sharey:
1172+
if self._sharey is not None:
11521173
self.yaxis.set_visible(yaxis_visible)
11531174
self.patch.set_visible(patch_visible)
11541175

0 commit comments

Comments
 (0)