@@ -488,25 +488,15 @@ def __init__(self, fig, rect,
488
488
self ._originalPosition = self ._position .frozen ()
489
489
# self.set_axes(self)
490
490
self .axes = self
491
- self .set_aspect ( 'auto' )
491
+ self ._aspect = 'auto'
492
492
self ._adjustable = 'box'
493
- self .set_anchor ( 'C' )
493
+ self ._anchor = 'C'
494
494
self ._sharex = sharex
495
495
self ._sharey = sharey
496
496
if sharex is not None :
497
497
self ._shared_x_axes .join (self , sharex )
498
- if sharex ._adjustable == 'box' :
499
- sharex ._adjustable = 'datalim'
500
- # warnings.warn(
501
- # 'shared axes: "adjustable" is being changed to "datalim"')
502
- self ._adjustable = 'datalim'
503
498
if sharey is not None :
504
499
self ._shared_y_axes .join (self , sharey )
505
- if sharey ._adjustable == 'box' :
506
- sharey ._adjustable = 'datalim'
507
- # warnings.warn(
508
- # 'shared axes: "adjustable" is being changed to "datalim"')
509
- self ._adjustable = 'datalim'
510
500
self .set_label (label )
511
501
self .set_figure (fig )
512
502
@@ -537,7 +527,11 @@ def __init__(self, fig, rect,
537
527
self ._hold = True
538
528
539
529
self ._connected = {} # a dict from events to (id, func)
540
- self .cla ()
530
+ try :
531
+ self .cla (clear_axis = False ) # new xaxis and yaxis are already cleared
532
+ except TypeError :
533
+ self .cla () # For Axes subclasses lacking clear_axis argument.
534
+
541
535
# funcs used to format x and y - fall back on major formatters
542
536
self .fmt_xdata = None
543
537
self .fmt_ydata = None
@@ -607,11 +601,11 @@ def get_window_extent(self, *args, **kwargs):
607
601
def _init_axis (self ):
608
602
"move this out of __init__ because non-separable axes don't use it"
609
603
self .xaxis = maxis .XAxis (self )
610
- self .spines ['bottom' ].register_axis (self .xaxis )
611
- self .spines ['top' ].register_axis (self .xaxis )
604
+ self .spines ['bottom' ].register_axis (self .xaxis , clear_axis = False )
605
+ self .spines ['top' ].register_axis (self .xaxis , clear_axis = False )
612
606
self .yaxis = maxis .YAxis (self )
613
- self .spines ['left' ].register_axis (self .yaxis )
614
- self .spines ['right' ].register_axis (self .yaxis )
607
+ self .spines ['left' ].register_axis (self .yaxis , clear_axis = False )
608
+ self .spines ['right' ].register_axis (self .yaxis , clear_axis = False )
615
609
self ._update_transScale ()
616
610
617
611
def set_figure (self , fig ):
@@ -634,8 +628,7 @@ def set_figure(self, fig):
634
628
635
629
def _set_lim_and_transforms (self ):
636
630
"""
637
- set the *dataLim* and *viewLim*
638
- :class:`~matplotlib.transforms.Bbox` attributes and the
631
+ set the *_xaxis_transform*, *_yaxis_transform*,
639
632
*transScale*, *transData*, *transLimits* and *transAxes*
640
633
transformations.
641
634
@@ -952,7 +945,7 @@ def _gen_axes_spines(self, locations=None, offset=0.0, units='inches'):
952
945
('bottom' , mspines .Spine .linear_spine (self , 'bottom' )),
953
946
('top' , mspines .Spine .linear_spine (self , 'top' ))])
954
947
955
- def cla (self ):
948
+ def cla (self , clear_axis = True ):
956
949
"""Clear the current axes."""
957
950
# Note: this is called by Axes.__init__()
958
951
@@ -965,51 +958,46 @@ def cla(self):
965
958
xaxis_visible = self .xaxis .get_visible ()
966
959
yaxis_visible = self .yaxis .get_visible ()
967
960
968
- self .xaxis .cla ()
969
- self .yaxis .cla ()
961
+ # The axis cla() sets the scale and default locators and
962
+ # formatters. It needs to know if the axis is shared
963
+ # so that it can preserve the shared scale.
964
+ shared_x = self ._sharex .xaxis if self ._sharex else None
965
+ shared_y = self ._sharey .yaxis if self ._sharey else None
966
+
967
+ if clear_axis :
968
+ self .xaxis .cla (shared_x )
969
+ self .yaxis .cla (shared_y ) #
970
+
970
971
for name , spine in six .iteritems (self .spines ):
971
- spine .cla ()
972
+ spine .cla (clear_axis = False ) # Clears only the position.
972
973
973
974
self .ignore_existing_data_limits = True
974
975
self .callbacks = cbook .CallbackRegistry ()
975
976
976
- if self . _sharex is not None :
977
- # major and minor are class instances with
977
+ if shared_x is not None :
978
+ # major and minor are axis.Ticker class instances with
978
979
# locator and formatter attributes
979
- self .xaxis .major = self . _sharex . xaxis .major
980
- self .xaxis .minor = self . _sharex . xaxis .minor
980
+ self .xaxis .major = shared_x .major
981
+ self .xaxis .minor = shared_x .minor
981
982
x0 , x1 = self ._sharex .get_xlim ()
982
983
self .set_xlim (x0 , x1 , emit = False , auto = None )
983
- self .xaxis ._scale = mscale .scale_factory (
984
- self ._sharex .xaxis .get_scale (), self .xaxis )
985
984
else :
986
- self .xaxis ._set_scale ('linear' )
987
985
try :
988
986
self .set_xlim (0 , 1 )
989
987
except TypeError :
990
988
pass
991
989
992
- if self . _sharey is not None :
993
- self .yaxis .major = self . _sharey . yaxis .major
994
- self .yaxis .minor = self . _sharey . yaxis .minor
990
+ if shared_y is not None :
991
+ self .yaxis .major = shared_y .major
992
+ self .yaxis .minor = shared_y .minor
995
993
y0 , y1 = self ._sharey .get_ylim ()
996
994
self .set_ylim (y0 , y1 , emit = False , auto = None )
997
- self .yaxis ._scale = mscale .scale_factory (
998
- self ._sharey .yaxis .get_scale (), self .yaxis )
999
995
else :
1000
- self .yaxis ._set_scale ('linear' )
1001
996
try :
1002
997
self .set_ylim (0 , 1 )
1003
998
except TypeError :
1004
999
pass
1005
1000
1006
- # update the minor locator for x and y axis based on rcParams
1007
- if (rcParams ['xtick.minor.visible' ]):
1008
- self .xaxis .set_minor_locator (mticker .AutoMinorLocator ())
1009
-
1010
- if (rcParams ['ytick.minor.visible' ]):
1011
- self .yaxis .set_minor_locator (mticker .AutoMinorLocator ())
1012
-
1013
1001
self ._autoscaleXon = True
1014
1002
self ._autoscaleYon = True
1015
1003
self ._xmargin = rcParams ['axes.xmargin' ]
@@ -1093,6 +1081,14 @@ def cla(self):
1093
1081
self .yaxis .set_visible (yaxis_visible )
1094
1082
self .patch .set_visible (patch_visible )
1095
1083
1084
+ # It is not clear to me (EF) why this reset is needed here, but
1085
+ # it does seem to be needed somewhere in this vicinity. Otherwise,
1086
+ # setting tick rotation via set_params doesn't work until the
1087
+ # first draw has occurred.
1088
+ self .xaxis .reset_ticks ()
1089
+ self .yaxis .reset_ticks ()
1090
+
1091
+
1096
1092
self .stale = True
1097
1093
1098
1094
@cbook .deprecated ("2.1" , alternative = "Axes.patch" )
@@ -1224,7 +1220,7 @@ def hold(self, b=None):
1224
1220
def get_aspect (self ):
1225
1221
return self ._aspect
1226
1222
1227
- def set_aspect (self , aspect , adjustable = None , anchor = None ):
1223
+ def set_aspect (self , aspect , adjustable = None , anchor = None , share = False ):
1228
1224
"""
1229
1225
*aspect*
1230
1226
@@ -1245,12 +1241,9 @@ def set_aspect(self, aspect, adjustable=None, anchor=None):
1245
1241
============ =====================================
1246
1242
'box' change physical size of axes
1247
1243
'datalim' change xlim or ylim
1248
- 'box-forced' same as 'box', but axes can be shared
1249
1244
============ =====================================
1250
1245
1251
- 'box' does not allow axes sharing, as this can cause
1252
- unintended side effect. For cases when sharing axes is
1253
- fine, use 'box-forced'.
1246
+ When both axes are shared, only 'box' is allowable.
1254
1247
1255
1248
*anchor*
1256
1249
@@ -1270,24 +1263,40 @@ def set_aspect(self, aspect, adjustable=None, anchor=None):
1270
1263
else :
1271
1264
self ._aspect = float (aspect ) # raise ValueError if necessary
1272
1265
1273
- if adjustable is not None :
1274
- self .set_adjustable (adjustable )
1266
+ if share and self in self ._shared_x_axes :
1267
+ for ax in self ._shared_x_axes .get_siblings (self ):
1268
+ ax ._aspect = aspect
1269
+ if share and self in self ._shared_y_axes :
1270
+ for ax in self ._shared_y_axes .get_siblings (self ):
1271
+ ax ._aspect = aspect
1272
+
1273
+ if adjustable is None :
1274
+ adjustable = self ._adjustable
1275
+ self .set_adjustable (adjustable , share = share ) # Always call this to handle sharing.
1276
+
1275
1277
if anchor is not None :
1276
1278
self .set_anchor (anchor )
1277
1279
self .stale = True
1278
1280
1279
1281
def get_adjustable (self ):
1280
1282
return self ._adjustable
1281
1283
1282
- def set_adjustable (self , adjustable ):
1284
+ def set_adjustable (self , adjustable , share = False ):
1283
1285
"""
1284
- ACCEPTS: [ 'box' | 'datalim' | 'box-forced' ]
1286
+ ACCEPTS: [ 'box' | 'datalim']
1285
1287
"""
1288
+ # FIXME: add box-forced deprecation
1286
1289
if adjustable in ('box' , 'datalim' , 'box-forced' ):
1287
- if self in self ._shared_x_axes or self in self ._shared_y_axes :
1288
- if adjustable == 'box ' :
1290
+ if self in self ._shared_x_axes and self in self ._shared_y_axes :
1291
+ if adjustable == 'datalim ' :
1289
1292
raise ValueError (
1290
- 'adjustable must be "datalim" for shared axes' )
1293
+ 'adjustable must be "box" when both axes are shared' )
1294
+ if share and self in self ._shared_x_axes :
1295
+ for ax in self ._shared_x_axes .get_siblings (self ):
1296
+ ax ._adjustable = adjustable
1297
+ if share and self in self ._shared_y_axes :
1298
+ for ax in self ._shared_y_axes .get_siblings (self ):
1299
+ ax ._adjustable = adjustable
1291
1300
self ._adjustable = adjustable
1292
1301
else :
1293
1302
raise ValueError ('argument must be "box", or "datalim"' )
@@ -1387,14 +1396,6 @@ def apply_aspect(self, position=None):
1387
1396
else :
1388
1397
A = aspect
1389
1398
1390
- # Ensure at drawing time that any Axes involved in axis-sharing
1391
- # does not have its position changed.
1392
- if self in self ._shared_x_axes or self in self ._shared_y_axes :
1393
- if self ._adjustable == 'box' :
1394
- self ._adjustable = 'datalim'
1395
- warnings .warn (
1396
- 'shared axes: "adjustable" is being changed to "datalim"' )
1397
-
1398
1399
figW , figH = self .get_figure ().get_size_inches ()
1399
1400
fig_aspect = figH / figW
1400
1401
if self ._adjustable in ['box' , 'box-forced' ]:
@@ -1452,23 +1453,24 @@ def apply_aspect(self, position=None):
1452
1453
xm = 0
1453
1454
ym = 0
1454
1455
1455
- changex = ( self in self ._shared_y_axes and
1456
- self not in self ._shared_x_axes )
1457
- changey = ( self in self . _shared_x_axes and
1458
- self not in self . _shared_y_axes )
1459
- if changex and changey :
1460
- warnings . warn ( "adjustable='datalim' cannot work with shared "
1461
- "x and y axes" )
1462
- return
1463
- if changex :
1456
+ shared_x = self in self ._shared_x_axes
1457
+ shared_y = self in self ._shared_y_axes
1458
+ # Not sure whether we need this check:
1459
+ if shared_x and shared_y :
1460
+ raise RuntimeError ( "adjustable='datalim' is not allowed when both"
1461
+ " axes are shared." )
1462
+
1463
+ # If y is shared, then we are only allowed to change x, etc.
1464
+ if shared_y :
1464
1465
adjust_y = False
1465
1466
else :
1466
1467
if xmarg > xm and ymarg > ym :
1467
1468
adjy = ((Ymarg > 0 and y_expander < 0 ) or
1468
1469
(Xmarg < 0 and y_expander > 0 ))
1469
1470
else :
1470
1471
adjy = y_expander > 0
1471
- adjust_y = changey or adjy # (Ymarg > xmarg)
1472
+ adjust_y = shared_x or adjy # (Ymarg > xmarg)
1473
+
1472
1474
if adjust_y :
1473
1475
yc = 0.5 * (ymin + ymax )
1474
1476
y0 = yc - Ysize / 2.0
@@ -3977,9 +3979,9 @@ def twiny(self):
3977
3979
return ax2
3978
3980
3979
3981
def get_shared_x_axes (self ):
3980
- 'Return a copy of the shared axes Grouper object for x axes'
3982
+ 'Return a reference to the shared axes Grouper object for x axes'
3981
3983
return self ._shared_x_axes
3982
3984
3983
3985
def get_shared_y_axes (self ):
3984
- 'Return a copy of the shared axes Grouper object for y axes'
3986
+ 'Return a reference to the shared axes Grouper object for y axes'
3985
3987
return self ._shared_y_axes
0 commit comments