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

Commitc1b51aa

Browse files
ZachDaChampionQuLogic
authored andcommitted
Allow passing a transformation to secondary_[xy]axis
Add transform argument to secondary axesUpdate _secax_docstringMove new params to end of functionsAdd input check to secondary axesAdd testsAdd examplesMove transform type checks and improve docsAdd type stubsUpdate _secax_docstringMove new params to end of functionsAdd input check to secondary axesMove transform type checks and improve docsFix rebase errorFix stub for SecondaryAxis.__init__Clarify exampleAdd default param to secax constructorFix stub for secax constructorSimplify importsCo-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>Remove redundancy in docsCo-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>Fix typo
1 parent88d64e5 commitc1b51aa

File tree

7 files changed

+103
-21
lines changed

7 files changed

+103
-21
lines changed

‎galleries/examples/subplots_axes_and_figures/secondary_axis.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,25 @@ def rad2deg(x):
4040
secax.set_xlabel('angle [rad]')
4141
plt.show()
4242

43+
# %%
44+
# By default, the secondary axis is drawn in the Axes coordinate space.
45+
# We can also provide a custom transform to place it in a different
46+
# coordinate space. Here we put the axis at Y = 0 in data coordinates.
47+
48+
fig,ax=plt.subplots(layout='constrained')
49+
x=np.arange(0,10)
50+
np.random.seed(19680801)
51+
y=np.random.randn(len(x))
52+
ax.plot(x,y)
53+
ax.set_xlabel('X')
54+
ax.set_ylabel('Y')
55+
ax.set_title('Random data')
56+
57+
# Pass ax.transData as a transform to place the axis relative to our data
58+
secax=ax.secondary_xaxis(0,transform=ax.transData)
59+
secax.set_xlabel('Axis at Y = 0')
60+
plt.show()
61+
4362
# %%
4463
# Here is the case of converting from wavenumber to wavelength in a
4564
# log-log scale.

‎lib/matplotlib/axes/_axes.py

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ def indicate_inset_zoom(self, inset_ax, **kwargs):
551551
returnself.indicate_inset(rect,inset_ax,**kwargs)
552552

553553
@_docstring.dedent_interpd
554-
defsecondary_xaxis(self,location,*,functions=None,**kwargs):
554+
defsecondary_xaxis(self,location,*,functions=None,transform=None,**kwargs):
555555
"""
556556
Add a second x-axis to this `~.axes.Axes`.
557557
@@ -582,18 +582,30 @@ def invert(x):
582582
secax = ax.secondary_xaxis('top', functions=(invert, invert))
583583
secax.set_xlabel('Period [s]')
584584
plt.show()
585+
586+
To add a secondary axis relative to your data, you can pass a transform
587+
to the new axis.
588+
589+
.. plot::
590+
591+
fig, ax = plt.subplots()
592+
ax.plot(range(0, 5), range(-1, 4))
593+
594+
# Pass 'ax.transData' as a transform to place the axis
595+
# relative to your data at y=0
596+
secax = ax.secondary_xaxis(0, transform=ax.transData)
585597
"""
586-
iflocationin ['top','bottom']orisinstance(location,Real):
587-
secondary_ax=SecondaryAxis(self,'x',location,functions,
588-
**kwargs)
589-
self.add_child_axes(secondary_ax)
590-
returnsecondary_ax
591-
else:
598+
ifnot (locationin ['top','bottom']orisinstance(location,Real)):
592599
raiseValueError('secondary_xaxis location must be either '
593600
'a float or "top"/"bottom"')
594601

602+
secondary_ax=SecondaryAxis(self,'x',location,functions,
603+
transform,**kwargs)
604+
self.add_child_axes(secondary_ax)
605+
returnsecondary_ax
606+
595607
@_docstring.dedent_interpd
596-
defsecondary_yaxis(self,location,*,functions=None,**kwargs):
608+
defsecondary_yaxis(self,location,*,functions=None,transform=None,**kwargs):
597609
"""
598610
Add a second y-axis to this `~.axes.Axes`.
599611
@@ -614,16 +626,28 @@ def secondary_yaxis(self, location, *, functions=None, **kwargs):
614626
secax = ax.secondary_yaxis('right', functions=(np.deg2rad,
615627
np.rad2deg))
616628
secax.set_ylabel('radians')
629+
630+
To add a secondary axis relative to your data, you can pass a transform
631+
to the new axis.
632+
633+
.. plot::
634+
635+
fig, ax = plt.subplots()
636+
ax.plot(range(0, 5), range(-1, 4))
637+
638+
# Pass 'ax.transData' as a transform to place the axis
639+
# relative to your data at x=3
640+
secax = ax.secondary_yaxis(3, transform=ax.transData)
617641
"""
618-
iflocationin ['left','right']orisinstance(location,Real):
619-
secondary_ax=SecondaryAxis(self,'y',location,
620-
functions,**kwargs)
621-
self.add_child_axes(secondary_ax)
622-
returnsecondary_ax
623-
else:
642+
ifnot (locationin ['left','right']orisinstance(location,Real)):
624643
raiseValueError('secondary_yaxis location must be either '
625644
'a float or "left"/"right"')
626645

646+
secondary_ax=SecondaryAxis(self,'y',location,functions,
647+
transform,**kwargs)
648+
self.add_child_axes(secondary_ax)
649+
returnsecondary_ax
650+
627651
@_docstring.dedent_interpd
628652
deftext(self,x,y,s,fontdict=None,**kwargs):
629653
"""

‎lib/matplotlib/axes/_axes.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class Axes(_AxesBase):
9494
]
9595
|Transform
9696
|None= ...,
97+
transform:Transform|None= ...,
9798
**kwargs
9899
)->SecondaryAxis: ...
99100
defsecondary_yaxis(
@@ -105,6 +106,7 @@ class Axes(_AxesBase):
105106
]
106107
|Transform
107108
|None= ...,
109+
transform:Transform|None= ...,
108110
**kwargs
109111
)->SecondaryAxis: ...
110112
deftext(

‎lib/matplotlib/axes/_secondary_axes.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
importnumpyasnp
44

5-
frommatplotlibimport_api,_docstring
5+
frommatplotlibimport_api,_docstring,transforms
66
importmatplotlib.tickerasmticker
77
frommatplotlib.axes._baseimport_AxesBase,_TransformedBoundsLocator
88
frommatplotlib.axisimportAxis
@@ -14,7 +14,8 @@ class SecondaryAxis(_AxesBase):
1414
General class to hold a Secondary_X/Yaxis.
1515
"""
1616

17-
def__init__(self,parent,orientation,location,functions,**kwargs):
17+
def__init__(self,parent,orientation,location,functions,transform=None,
18+
**kwargs):
1819
"""
1920
See `.secondary_xaxis` and `.secondary_yaxis` for the doc string.
2021
While there is no need for this to be private, it should really be
@@ -39,7 +40,7 @@ def __init__(self, parent, orientation, location, functions, **kwargs):
3940
self._parentscale=None
4041
# this gets positioned w/o constrained_layout so exclude:
4142

42-
self.set_location(location)
43+
self.set_location(location,transform)
4344
self.set_functions(functions)
4445

4546
# styling:
@@ -74,7 +75,7 @@ def set_alignment(self, align):
7475
self._axis.set_ticks_position(align)
7576
self._axis.set_label_position(align)
7677

77-
defset_location(self,location):
78+
defset_location(self,location,transform=None):
7879
"""
7980
Set the vertical or horizontal location of the axes in
8081
parent-normalized coordinates.
@@ -87,8 +88,17 @@ def set_location(self, location):
8788
orientation='y'. A float indicates the relative position on the
8889
parent Axes to put the new Axes, 0.0 being the bottom (or left)
8990
and 1.0 being the top (or right).
91+
92+
transform : `.Transform`, optional
93+
Transform for the location to use. Defaults to
94+
the parent's ``transAxes``, so locations are normally relative to
95+
the parent axes.
96+
97+
.. versionadded:: 3.9
9098
"""
9199

100+
_api.check_isinstance((transforms.Transform,None),transform=transform)
101+
92102
# This puts the rectangle into figure-relative coordinates.
93103
ifisinstance(location,str):
94104
_api.check_in_list(self._locstrings,location=location)
@@ -106,15 +116,28 @@ def set_location(self, location):
106116
# An x-secondary axes is like an inset axes from x = 0 to x = 1 and
107117
# from y = pos to y = pos + eps, in the parent's transAxes coords.
108118
bounds= [0,self._pos,1.,1e-10]
119+
120+
# If a transformation is provided, use its y component rather than
121+
# the parent's transAxes. This can be used to place axes in the data
122+
# coords, for instance.
123+
iftransformisnotNone:
124+
transform=transforms.blended_transform_factory(
125+
self._parent.transAxes,transform)
109126
else:# 'y'
110127
bounds= [self._pos,0,1e-10,1]
128+
iftransformisnotNone:
129+
transform=transforms.blended_transform_factory(
130+
transform,self._parent.transAxes)# Use provided x axis
131+
132+
# If no transform is provided, use the parent's transAxes
133+
iftransformisNone:
134+
transform=self._parent.transAxes
111135

112136
# this locator lets the axes move in the parent axes coordinates.
113137
# so it never needs to know where the parent is explicitly in
114138
# figure coordinates.
115139
# it gets called in ax.apply_aspect() (of all places)
116-
self.set_axes_locator(
117-
_TransformedBoundsLocator(bounds,self._parent.transAxes))
140+
self.set_axes_locator(_TransformedBoundsLocator(bounds,transform))
118141

119142
defapply_aspect(self,position=None):
120143
# docstring inherited.
@@ -278,6 +301,14 @@ def set_color(self, color):
278301
See :doc:`/gallery/subplots_axes_and_figures/secondary_axis`
279302
for examples of making these conversions.
280303
304+
transform : `.Transform`, optional
305+
If specified, *location* will be
306+
placed relative to this transform (in the direction of the axis)
307+
rather than the parent's axis. i.e. a secondary x-axis will
308+
use the provided y transform and the x transform of the parent.
309+
310+
.. versionadded:: 3.9
311+
281312
Returns
282313
-------
283314
ax : axes._secondary_axes.SecondaryAxis

‎lib/matplotlib/axes/_secondary_axes.pyi

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,16 @@ class SecondaryAxis(_AxesBase):
1818
Callable[[ArrayLike],ArrayLike],Callable[[ArrayLike],ArrayLike]
1919
]
2020
|Transform,
21+
transform:Transform|None= ...,
2122
**kwargs
2223
)->None: ...
2324
defset_alignment(
2425
self,align:Literal["top","bottom","right","left"]
2526
)->None: ...
2627
defset_location(
27-
self,location:Literal["top","bottom","right","left"]|float
28+
self,
29+
location:Literal["top","bottom","right","left"]|float,
30+
transform:Transform|None= ...
2831
)->None: ...
2932
defset_ticks(
3033
self,

‎lib/matplotlib/tests/test_axes.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7528,6 +7528,7 @@ def invert(x):
75287528
secax(0.6,functions=(lambdax:x**2,lambdax:x**(1/2)))
75297529
secax(0.8)
75307530
secax("top"ifnn==0else"right",functions=_Translation(2))
7531+
secax(6.25,transform=ax.transData)
75317532

75327533

75337534
deftest_secondary_fail():
@@ -7539,6 +7540,8 @@ def test_secondary_fail():
75397540
ax.secondary_xaxis('right')
75407541
withpytest.raises(ValueError):
75417542
ax.secondary_yaxis('bottom')
7543+
withpytest.raises(TypeError):
7544+
ax.secondary_xaxis(0.2,transform='error')
75427545

75437546

75447547
deftest_secondary_resize():

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp