Skip to content

Commit b1d6a54

Browse files
committed
feat: axes class and kwargs for twinx and twiny
1 parent 3aebcb7 commit b1d6a54

File tree

3 files changed

+42
-7
lines changed

3 files changed

+42
-7
lines changed

lib/matplotlib/axes/_base.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4600,7 +4600,7 @@ def _make_twin_axes(self, *args, **kwargs):
46004600
self._twinned_axes.join(self, twin)
46014601
return twin
46024602

4603-
def twinx(self):
4603+
def twinx(self, **kwargs):
46044604
"""
46054605
Create a twin Axes sharing the xaxis.
46064606
@@ -4610,6 +4610,11 @@ def twinx(self):
46104610
Axes. To ensure that the tick marks of both y-axes align, see
46114611
`~matplotlib.ticker.LinearLocator`.
46124612
4613+
Parameters
4614+
----------
4615+
kwargs : dict
4616+
The keyword arguments passed to ``add_subplot()`` or ``add_axes()``.
4617+
46134618
Returns
46144619
-------
46154620
Axes
@@ -4620,7 +4625,7 @@ def twinx(self):
46204625
For those who are 'picking' artists while using twinx, pick
46214626
events are only called for the artists in the top-most Axes.
46224627
"""
4623-
ax2 = self._make_twin_axes(sharex=self)
4628+
ax2 = self._make_twin_axes(sharex=self, axes_class=type(self), **kwargs)
46244629
ax2.yaxis.tick_right()
46254630
ax2.yaxis.set_label_position('right')
46264631
ax2.yaxis.set_offset_position('right')
@@ -4631,7 +4636,7 @@ def twinx(self):
46314636
ax2.xaxis.units = self.xaxis.units
46324637
return ax2
46334638

4634-
def twiny(self):
4639+
def twiny(self, **kwargs):
46354640
"""
46364641
Create a twin Axes sharing the yaxis.
46374642
@@ -4641,6 +4646,11 @@ def twiny(self):
46414646
To ensure that the tick marks of both x-axes align, see
46424647
`~matplotlib.ticker.LinearLocator`.
46434648
4649+
Parameters
4650+
----------
4651+
kwargs : dict
4652+
The keyword arguments passed to ``add_subplot()`` or ``add_axes()``.
4653+
46444654
Returns
46454655
-------
46464656
Axes
@@ -4651,7 +4661,7 @@ def twiny(self):
46514661
For those who are 'picking' artists while using twiny, pick
46524662
events are only called for the artists in the top-most Axes.
46534663
"""
4654-
ax2 = self._make_twin_axes(sharey=self)
4664+
ax2 = self._make_twin_axes(sharey=self, axes_class=type(self), **kwargs)
46554665
ax2.xaxis.tick_top()
46564666
ax2.xaxis.set_label_position('top')
46574667
ax2.set_autoscaley_on(self.get_autoscaley_on())

lib/matplotlib/axes/_base.pyi

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import datetime
44
from collections.abc import Callable, Iterable, Iterator, Sequence
55
from matplotlib import cbook
66
from matplotlib.artist import Artist
7-
from matplotlib.axes import Axes
87
from matplotlib.axis import XAxis, YAxis, Tick
98
from matplotlib.backend_bases import RendererBase, MouseButton, MouseEvent
109
from matplotlib.cbook import CallbackRegistry
@@ -29,6 +28,7 @@ import numpy as np
2928
from numpy.typing import ArrayLike
3029
from typing import Any, Literal, TypeVar, overload
3130
from matplotlib.typing import ColorType
31+
from typing_extensions import Self
3232

3333
_T = TypeVar("_T", bound=Artist)
3434

@@ -385,8 +385,8 @@ class _AxesBase(martist.Artist):
385385
bbox_extra_artists: Sequence[Artist] | None = ...,
386386
for_layout_only: bool = ...
387387
) -> Bbox | None: ...
388-
def twinx(self) -> Axes: ...
389-
def twiny(self) -> Axes: ...
388+
def twinx(self, **kwargs) -> Self: ...
389+
def twiny(self, **kwargs) -> Self: ...
390390
def get_shared_x_axes(self) -> cbook.GrouperView: ...
391391
def get_shared_y_axes(self) -> cbook.GrouperView: ...
392392
def label_outer(self, remove_inner_ticks: bool = ...) -> None: ...

lib/matplotlib/tests/test_axes.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7532,6 +7532,31 @@ def test_twinx_knows_limits():
75327532
assert_array_equal(xtwin.viewLim.intervalx, ax2.viewLim.intervalx)
75337533

75347534

7535+
class SubclassAxes(Axes):
7536+
def __init__(self, *args, ax=None, foo, **kwargs):
7537+
if ax is None:
7538+
super().__init__(*args, **kwargs)
7539+
else:
7540+
self.__dict__.update(ax.__dict__)
7541+
self.foo = foo
7542+
7543+
7544+
@pytest.mark.parametrize(("axes_class", "kw0", "kw1"), [
7545+
(Axes, {}, {}),
7546+
(SubclassAxes, {"foo": 0}, {"foo": 1}),
7547+
])
7548+
def test_twinx_subclass(axes_class, kw0, kw1):
7549+
_, ax = plt.subplots()
7550+
classed_ax = ax if axes_class is Axes else axes_class(ax=ax, **kw0)
7551+
for k, v in kw0.items():
7552+
assert getattr(classed_ax, k) == v
7553+
7554+
twin = classed_ax.twinx(**kw1)
7555+
assert type(twin) is axes_class
7556+
for k, v in kw1.items():
7557+
assert getattr(twin, k) == v
7558+
7559+
75357560
def test_zero_linewidth():
75367561
# Check that setting a zero linewidth doesn't error
75377562
plt.plot([0, 1], [0, 1], ls='--', lw=0)

0 commit comments

Comments
 (0)