@@ -540,8 +540,8 @@ def _plot_args(self, tup, kwargs, return_kwargs=False):
540
540
class _AxesBase (martist .Artist ):
541
541
name = "rectilinear"
542
542
543
- _shared_x_axes = cbook . Grouper ()
544
- _shared_y_axes = cbook .Grouper ()
543
+ _axis_names = ( "x" , "y" ) # See _get_axis_map.
544
+ _shared_axes = { name : cbook .Grouper () for name in _axis_names }
545
545
_twinned_axes = cbook .Grouper ()
546
546
547
547
def __str__ (self ):
@@ -606,8 +606,7 @@ def __init__(self, fig, rect,
606
606
self ._aspect = 'auto'
607
607
self ._adjustable = 'box'
608
608
self ._anchor = 'C'
609
- self ._stale_viewlim_x = False
610
- self ._stale_viewlim_y = False
609
+ self ._stale_viewlims = {name : False for name in self ._axis_names }
611
610
self ._sharex = sharex
612
611
self ._sharey = sharey
613
612
self .set_label (label )
@@ -685,20 +684,21 @@ def __getstate__(self):
685
684
# that point.
686
685
state = super ().__getstate__ ()
687
686
# Prune the sharing & twinning info to only contain the current group.
688
F438
- for grouper_name in [
689
- '_shared_x_axes' , '_shared_y_axes' , '_twinned_axes' ]:
690
- grouper = getattr ( self , grouper_name )
691
- state [grouper_name ] = (grouper .get_siblings (self )
692
- if self in grouper else None )
687
+ state [ "_shared_axes" ] = {
688
+ name : self . _shared_axes [ name ]. get_siblings ( self )
689
+ for name in self . _axis_names if self in self . _shared_axes [ name ]}
690
+ state ["_twinned_axes" ] = (self . _twinned_axes .get_siblings (self )
691
+ if self in self . _twinned_axes else None )
693
692
return state
694
693
695
694
def __setstate__ (self , state ):
696
695
# Merge the grouping info back into the global groupers.
697
- for grouper_name in [
698
- '_shared_x_axes' , '_shared_y_axes' , '_twinned_axes' ]:
699
- siblings = state .pop (grouper_name )
700
- if siblings :
701
- getattr (self , grouper_name ).join (* siblings )
696
+ shared_axes = state .pop ("_shared_axes" )
697
+ for name , shared_siblings in shared_axes .items ():
698
+ self ._shared_axes [name ].join (* shared_siblings )
699
+ twinned_siblings = state .pop ("_twinned_axes" )
700
+ if twinned_siblings :
701
+ self ._twinned_axes .join (* twinned_siblings )
702
702
self .__dict__ = state
703
703
self ._stale = True
704
704
@@ -763,16 +763,16 @@ def set_figure(self, fig):
763
763
def _unstale_viewLim (self ):
764
764
# We should arrange to store this information once per share-group
765
765
# instead of on every axis.
766
- scalex = any ( ax . _stale_viewlim_x
767
- for ax in self . _shared_x_axes . get_siblings ( self ))
768
- scaley = any ( ax . _stale_viewlim_y
769
- for ax in self ._shared_y_axes . get_siblings ( self ))
770
- if scalex or scaley :
771
- for ax in self . _shared_x_axes . get_siblings ( self ) :
772
- ax . _stale_viewlim_x = False
773
- for ax in self . _shared_y_axes . get_siblings ( self ):
774
- ax . _stale_viewlim_y = False
775
- self . autoscale_view ( scalex = scalex , scaley = scaley )
766
+ need_scale = {
767
+ name : any ( ax . _stale_viewlims [ name ]
768
+ for ax in self . _shared_axes [ name ]. get_siblings ( self ))
769
+ for name in self ._axis_names }
770
+ if any ( need_scale . values ()) :
771
+ for name in need_scale :
772
+ for ax in self . _shared_axes [ name ]. get_siblings ( self ):
773
+ ax . _stale_viewlims [ name ] = False
774
+ self . autoscale_view ( ** { f"scale { name } " : scale
775
+ for name , scale in need_scale . items ()} )
776
776
777
777
@property
778
778
def viewLim (self ):
@@ -781,13 +781,22 @@ def viewLim(self):
781
781
782
782
# API could be better, right now this is just to match the old calls to
783
783
# autoscale_view() after each plotting method.
784
- def _request_autoscale_view (self , tight = None , scalex = True , scaley = True ):
784
+ def _request_autoscale_view (self , tight = None , ** kwargs ):
785
+ # kwargs are "scalex", "scaley" (& "scalez" for 3D) and default to True
786
+ want_scale = {name : True for name in self ._axis_names }
787
+ for k , v in kwargs .items (): # Validate args before changing anything.
788
+ if k .startswith ("scale" ):
789
+ name = k [5 :]
790
+ if name in want_scale :
791
+ want_scale [name ] = v
792
+ continue
793
+ raise TypeError (
794
+ f"_request_autoscale_view() got an unexpected argument { k !r} " )
785
795
if tight is not None :
786
796
self ._tight = tight
787
- if scalex :
788
- self ._stale_viewlim_x = True # Else keep old state.
789
- if scaley :
790
- self ._stale_viewlim_y = True
797
+ for k , v in want_scale .items ():
798
+ if v :
799
+ self ._stale_viewlims [k ] = True # Else keep old state.
791
800
792
801
def _set_lim_and_transforms (self ):
793
802
"""
@@ -1141,7 +1150,7 @@ def sharex(self, other):
1141
1150
_api .check_isinstance (_AxesBase , other = other )
1142
1151
if self ._sharex is not None and other is not self ._sharex :
1143
1152
raise ValueError ("x-axis is already shared" )
1144
- self ._shared_x_axes .join (self , other )
1153
+ self ._shared_axes [ "x" ] .join (self , other )
1145
1154
self ._sharex = other
1146
1155
self .xaxis .major = other .xaxis .major # Ticker instances holding
1147
1156
self .xaxis .minor = other .xaxis .minor # locator and formatter.
@@ -1160,7 +1169,7 @@ def sharey(self, other):
1160
1169
_api .check_isinstance (_AxesBase , other = other )
1161
1170
if self ._sharey is not None and other is not self ._sharey :
1162
1171
raise ValueError ("y-axis is already shared" )
1163
- self ._shared_y_axes .join (self , other )
1172
+ self ._shared_axes [ "y" ] .join (self , other )
1164
1173
self ._sharey = other
1165
1174
self .yaxis .major = other .yaxis .major # Ticker instances holding
1166
1175
self .yaxis .minor = other .yaxis .minor # locator and formatter.
@@ -1289,8 +1298,8 @@ def cla(self):
1289
1298
self .xaxis .set_clip_path (self .patch )
1290
1299
self .yaxis .set_clip_path (self .patch )
1291
1300
1292
- self ._shared_x_axes .clean ()
1293
- self ._shared_y_axes .clean ()
1301
+ self ._shared_axes [ "x" ] .clean ()
1302
+ self ._shared_axes [ "y" ] .clean ()
1294
1303
if self ._sharex is not None :
1295
1304
self .xaxis .set_visible (xaxis_visible )
1296
1305
self .patch .set_visible (patch_visible )
@@ -1620,8 +1629,8 @@ def set_aspect(self, aspect, adjustable=None, anchor=None, share=False):
1620
1629
aspect = float (aspect ) # raise ValueError if necessary
1621
1630
1622
1631
if share :
1623
- axes = {* self ._shared_x_axes . get_siblings ( self ),
1624
- * self ._shared_y_axes .get_siblings (self )}
1632
+ axes = {sibling for name in self ._axis_names
1633
+ for sibling in self ._shared_axes [ name ] .get_siblings (self )}
1625
1634
else :
1626
1635
axes = [self ]
1627
1636
@@ -1682,8 +1691,8 @@ def set_adjustable(self, adjustable, share=False):
1682
1691
"""
1683
1692
_api .check_in_list (["box" , "datalim" ], adjustable = adjustable )
1684
1693
if share :
1685
- axs = {* self ._shared_x_axes . get_siblings ( self ),
1686
- * self ._shared_y_axes .get_siblings (self )}
1694
+ axs = {sibling for name in self ._axis_names
1695
+ for sibling in self ._shared_axes [ name ] .get_siblings (self )}
1687
1696
else :
1688
1697
axs = [self ]
1689
1698
if (adjustable == "datalim"
@@ -1803,8 +1812,8 @@ def set_anchor(self, anchor, share=False):
1803
1812
raise ValueError ('argument must be among %s' %
1804
1813
', ' .join (mtransforms .Bbox .coefs ))
1805
1814
if share :
1806
- axes = {* self ._shared_x_axes . get_siblings ( self ),
1807
- * self ._shared_y_axes .get_siblings (self )}
1815
+ axes = {sibling for name in self ._axis_names
1816
+ for sibling in self ._shared_axes [ name ] .get_siblings (self )}
1808
1817
else :
1809
1818
axes = [self ]
1810
1819
for ax in axes :
@@ -1919,8 +1928,8 @@ def apply_aspect(self, position=None):
1919
1928
xm = 0
1920
1929
ym = 0
1921
1930
1922
- shared_x = self in self ._shared_x_axes
1923
- shared_y = self in self ._shared_y_axes
1931
+ shared_x = self in self ._shared_axes [ "x" ]
1932
+ shared_y = self in self ._shared_axes [ "y" ]
1924
1933
# Not sure whether we need this check:
1925
1934
if shared_x and shared_y :
1926
1935
raise RuntimeError ("adjustable='datalim' is not allowed when both "
@@ -2830,13 +2839,13 @@ def autoscale_view(self, tight=None, scalex=True, scaley=True):
2830
2839
if self ._xmargin and scalex and self ._autoscaleXon :
2831
2840
x_stickies = np .sort (np .concatenate ([
2832
2841
artist .sticky_edges .x
2833
- for ax in self ._shared_x_axes .get_siblings (self )
2842
+ for ax in self ._shared_axes [ "x" ] .get_siblings (self )
2834
2843
if hasattr (ax , "_children" )
2835
2844
for artist in ax .get_children ()]))
2836
2845
if self ._ymargin and scaley and self ._autoscaleYon :
2837
2846
y_stickies = np .sort (np .concatenate ([
2838
2847
artist .sticky_edges .y
2839
- for ax in self ._shared_y_axes .get_siblings (self )
2848
+ for ax in self ._shared_axes [ "y" ] .get_siblings (self )
2840
2849
if hasattr (ax , "_children" )
2841
2850
for artist in ax .get_children ()]))
2842
2851
if self .get_xscale () == 'log' :
@@ -2910,14 +2919,14 @@ def handle_single_axis(scale, autoscaleon, shared_axes, name,
2910
2919
# End of definition of internal function 'handle_single_axis'.
2911
2920
2912
2921
handle_single_axis (
2913
- scalex , self ._autoscaleXon , self ._shared_x_axes , 'x' ,
2922
+ scalex , self ._autoscaleXon , self ._shared_axes [ "x" ] , 'x' ,
2914
2923
self .xaxis , self ._xmargin , x_stickies , self .set_xbound )
2915
2924
handle_single_axis (
2916
- scaley , self ._autoscaleYon , self ._shared_y_axes , 'y' ,
2925
+ scaley , self ._autoscaleYon , self ._shared_axes [ "y" ] , 'y' ,
2917
2926
self .yaxis , self ._ymargin , y_stickies , self .set_ybound )
2918
2927
2919
2928
def _get_axis_list (self ):
2920
- return self . xaxis , self .yaxis
2929
+ return tuple ( getattr ( self , f" { name } axis" ) for name in self ._axis_names )
2921
2930
2922
2931
def _get_axis_map (self ):
2923
2932
"""
@@ -2930,12 +2939,7 @@ def _get_axis_map(self):
2930
2939
In practice, this means that the entries are typically "x" and "y", and
2931
2940
additionally "z" for 3D axes.
2932
2941
"""
2933
- d = {}
2934
- axis_list = self ._get_axis_list ()
2935
- for k , v in vars (self ).items ():
2936
- if k .endswith ("axis" ) and v in axis_list :
2937
- d [k [:- len ("axis" )]] = v
2938
- return d
2942
+ return dict (zip (self ._axis_names , self ._get_axis_list ()))
2939
2943
2940
2944
def _update_title_position (self , renderer ):
2941
2945
"""
@@ -3706,15 +3710,15 @@ def set_xlim(self, left=None, right=None, emit=True, auto=False,
3706
3710
3707
3711
self ._viewLim .intervalx = (left , right )
3708
3712
# Mark viewlims as no longer stale without triggering an autoscale.
3709
- for ax in self ._shared_x_axes .get_siblings (self ):
3710
- ax ._stale_viewlim_x = False
3713
+ for ax in self ._shared_axes [ "x" ] .get_siblings (self ):
3714
+ ax ._stale_viewlims [ "x" ] = False
3711
3715
if auto is not None :
3712
3716
self ._autoscaleXon = bool (auto )
3713
3717
3714
3718
if emit :
3715
3719
self .callbacks .process ('xlim_changed' , self )
3716
3720
# Call all of the other x-axes that are shared with this one
3717
- for other in self ._shared_x_axes .get_siblings (self ):
3721
+ for other in self ._shared_axes [ "x" ] .get_siblings (self ):
3718
3722
if other is not self :
3719
3723
other .set_xlim (self .viewLim .intervalx ,
3720
3724
emit = False , auto = auto )
@@ -4033,15 +4037,15 @@ def set_ylim(self, bottom=None, top=None, emit=True, auto=False,
4033
4037
4034
4038
self ._viewLim .intervaly = (bottom , top )
4035
4039
# Mark viewlims as no longer stale without triggering an autoscale.
4036
- for ax in self ._shared_y_axes .get_siblings (self ):
4037
- ax ._stale_viewlim_y = False
4040
+ for ax in self ._shared_axes [ "y" ] .get_siblings (self ):
4041
+ ax ._stale_viewlims [ "y" ] = False
4038
4042
if auto is not None :
4039
4043
self ._autoscaleYon = bool (auto )
4040
4044
4041
4045
if emit :
4042
4046
self .callbacks .process ('ylim_changed' , self )
4043
4047
# Call all of the other y-axes that are shared with this one
4044
- for other in self ._shared_y_axes .get_siblings (self ):
4048
+ for other in self ._shared_axes [ "y" ] .get_siblings (self ):
4045
4049
if other is not self :
4046
4050
other .set_ylim (self .viewLim .intervaly ,
4047
4051
emit = False , auto = auto )
@@ -4705,8 +4709,8 @@ def twiny(self):
4705
4709
4706
4710
def get_shared_x_axes (self ):
4707
4711
"""Return a reference to the shared axes Grouper object for x axes."""
4708
- return self ._shared_x_axes
4712
+ return self ._shared_axes [ "x" ]
4709
4713
10000
tr>4710
4714
def get_shared_y_axes (self ):
4711
4715
"""Return a reference to the shared axes Grouper object for y axes."""
4712
- return self ._shared_y_axes
4716
+ return self ._shared_axes [ "y" ]
0 commit comments