Skip to content

Commit e4222e8

Browse files
committed
Merge pull request #4134 from cimarronm/3715_fix
BUG : Axis Labels with offset Spines Closes #3715
2 parents aa70121 + f49a5b6 commit e4222e8

File tree

3 files changed

+95
-40
lines changed

3 files changed

+95
-40
lines changed

lib/matplotlib/axis.py

+46-28
Original file line numberDiff line numberDiff line change
@@ -1581,8 +1581,8 @@ def set_ticks(self, ticks, minor=False):
15811581

15821582
def _update_label_position(self, bboxes, bboxes2):
15831583
"""
1584-
Update the label position based on the sequence of bounding
1585-
boxes of all the ticklabels
1584+
Update the label position based on the the bounding box enclosing
1585+
all the ticklabels and axis spine
15861586
"""
15871587
raise NotImplementedError('Derived must override')
15881588

@@ -1737,28 +1737,38 @@ def set_label_position(self, position):
17371737

17381738
def _update_label_position(self, bboxes, bboxes2):
17391739
"""
1740-
Update the label position based on the sequence of bounding
1741-
boxes of all the ticklabels
1740+
Update the label position based on the the bounding box enclosing
1741+
all the ticklabels and axis spine
17421742
"""
17431743
if not self._autolabelpos:
17441744
return
17451745
x, y = self.label.get_position()
17461746
if self.label_position == 'bottom':
1747-
if not len(bboxes):
1748-
bottom = self.axes.bbox.ymin
1749-
else:
1750-
bbox = mtransforms.Bbox.union(bboxes)
1751-
bottom = bbox.y0
1747+
try:
1748+
spine = self.axes.spines['bottom']
1749+
spinebbox = spine.get_transform().transform_path(
1750+
spine.get_path()).get_extents()
1751+
except KeyError:
1752+
# use axes if spine doesn't exist
1753+
spinebbox = self.axes.bbox
1754+
bbox = mtransforms.Bbox.union(bboxes + [spinebbox])
1755+
bottom = bbox.y0
1756+
17521757
self.label.set_position(
17531758
(x, bottom - self.labelpad * self.figure.dpi / 72.0)
17541759
)
17551760

17561761
else:
1757-
if not len(bboxes2):
1758-
top = self.axes.bbox.ymax
1759-
else:
1760-
bbox = mtransforms.Bbox.union(bboxes2)
1761-
top = bbox.y1
1762+
try:
1763+
spine = self.axes.spines['top']
1764+
spinebbox = spine.get_transform().transform_path(
1765+
spine.get_path()).get_extents()
1766+
except KeyError:
1767+
# use axes if spine doesn't exist
1768+
spinebbox = self.axes.bbox
1769+
bbox = mtransforms.Bbox.union(bboxes2 + [spinebbox])
1770+
top = bbox.y1
1771+
17621772
self.label.set_position(
17631773
(x, top + self.labelpad * self.figure.dpi / 72.0)
17641774
)
@@ -2043,29 +2053,37 @@ def set_label_position(self, position):
20432053

20442054
def _update_label_position(self, bboxes, bboxes2):
20452055
"""
2046-
Update the label position based on the sequence of bounding
2047-
boxes of all the ticklabels
2056+
Update the label position based on the the bounding box enclosing
2057+
all the ticklabels and axis spine
20482058
"""
20492059
if not self._autolabelpos:
20502060
return
20512061
x, y = self.label.get_position()
20522062
if self.label_position == 'left':
2053-
if not len(bboxes):
2054-
left = self.axes.bbox.xmin
2055-
else:
2056-
bbox = mtransforms.Bbox.union(bboxes)
2057-
left = bbox.x0
2063+
try:
2064+
spine = self.axes.spines['left']
2065+
spinebbox = spine.get_transform().transform_path(
2066+
spine.get_path()).get_extents()
2067+
except KeyError:
2068+
# use axes if spine doesn't exist
2069+
spinebbox = self.axes.bbox
2070+
bbox = mtransforms.Bbox.union(bboxes + [spinebbox])
2071+
left = bbox.x0
20582072

20592073
self.label.set_position(
20602074
(left - self.labelpad * self.figure.dpi / 72.0, y)
20612075
)
20622076

20632077
else:
2064-
if not len(bboxes2):
2065-
right = self.axes.bbox.xmax
2066-
else:
2067-
bbox = mtransforms.Bbox.union(bboxes2)
2068-
right = bbox.x1
2078+
try:
2079+
spine = self.axes.spines['right']
2080+
spinebbox = spine.get_transform().transform_path(
2081+
spine.get_path()).get_extents()
2082+
except KeyError:
2083+
# use axes if spine doesn't exist
2084+
spinebbox = self.axes.bbox
2085+
bbox = mtransforms.Bbox.union(bboxes2 + [spinebbox])
2086+
right = bbox.x1
20692087

20702088
self.label.set_position(
20712089
(right + self.labelpad * self.figure.dpi / 72.0, y)
@@ -2158,8 +2176,8 @@ def get_ticks_position(self):
21582176
majt = self.majorTicks[0]
21592177
mT = self.minorTicks[0]
21602178

2161-
majorRight = ((not majt.tick1On) and majt.tick2On
2162-
and (not majt.label1On) and majt.label2On)
2179+
majorRight = ((not majt.tick1On) and majt.tick2On and
2180+
(not majt.label1On) and majt.label2On)
21632181
minorRight = ((not mT.tick1On) and mT.tick2On and
21642182
(not mT.label1On) and mT.label2On)
21652183
if majorRight and minorRight:

lib/matplotlib/tests/test_coding_standards.py

-1
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,6 @@ def test_pep8_conformance_installed_files():
214214
'tests/test_mathtext.py',
215215
'tests/test_rcparams.py',
216216
'tests/test_simplification.py',
217-
'tests/test_spines.py',
218217
'tests/test_streamplot.py',
219218
'tests/test_subplots.py',
220219
'tests/test_tightlayout.py',

lib/matplotlib/tests/test_spines.py

+49-11
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,83 @@
11
from __future__ import (absolute_import, division, print_function,
22
unicode_literals)
33

4+
import numpy as np
5+
from nose.tools import assert_true
46
import six
57

6-
import numpy as np
78
import matplotlib
8-
from matplotlib.testing.decorators import image_comparison
99
import matplotlib.pyplot as plt
10+
import matplotlib.transforms as mtransforms
11+
from matplotlib.testing.decorators import image_comparison, cleanup
12+
1013

1114
@image_comparison(baseline_images=['spines_axes_positions'])
1215
def test_spines_axes_positions():
1316
# SF bug 2852168
1417
fig = plt.figure()
15-
x = np.linspace(0,2*np.pi,100)
18+
x = np.linspace(0, 2*np.pi, 100)
1619
y = 2*np.sin(x)
17-
ax = fig.add_subplot(1,1,1)
20+
ax = fig.add_subplot(1, 1, 1)
1821
ax.set_title('centered spines')
19-
ax.plot(x,y)
20-
ax.spines['right'].set_position(('axes',0.1))
22+
ax.plot(x, y)
23+
ax.spines['right'].set_position(('axes', 0.1))
2124
ax.yaxis.set_ticks_position('right')
22-
ax.spines['top'].set_position(('axes',0.25))
25+
ax.spines['top'].set_position(('axes', 0.25))
2326
ax.xaxis.set_ticks_position('top')
2427
ax.spines['left'].set_color('none')
2528
ax.spines['bottom'].set_color('none')
2629

30+
2731
@image_comparison(baseline_images=['spines_data_positions'])
2832
def test_spines_data_positions():
2933
fig = plt.figure()
30-
ax = fig.add_subplot(1,1,1)
34+
ax = fig.add_subplot(1, 1, 1)
3135
ax.spines['left'].set_position(('data', -1.5))
3236
ax.spines['top'].set_position(('data', 0.5))
3337
ax.spines['right'].set_position(('data', -0.5))
3438
ax.spines['bottom'].set_position('zero')
35-
ax.set_xlim([-2,2])
36-
ax.set_ylim([-2,2])
39+
ax.set_xlim([-2, 2])
40+
ax.set_ylim([-2, 2])
41+
3742

3843
@image_comparison(baseline_images=['spines_capstyle'])
3944
def test_spines_capstyle():
4045
# issue 2542
4146
plt.rc('axes', linewidth=20)
4247
fig = plt.figure()
43-
ax = fig.add_subplot(1,1,1)
48+
ax = fig.add_subplot(1, 1, 1)
4449
ax.set_xticks([])
4550
ax.set_yticks([])
51+
52+
53+
@cleanup
54+
def test_label_without_ticks():
55+
fig = plt.figure()
56+
ax = fig.add_subplot(1, 1, 1)
57+
plt.subplots_adjust(left=0.3, bottom=0.3)
58+
ax.plot(np.arange(10))
59+
ax.yaxis.set_ticks_position('left')
60+
ax.spines['left'].set_position(('outward', 30))
61+
ax.spines['right'].set_visible(False)
62+
ax.set_ylabel('y label')
63+
ax.xaxis.set_ticks_position('bottom')
64+
ax.spines['bottom'].set_position(('outward', 30))
65+
ax.spines['top'].set_visible(False)
66+
ax.set_xlabel('x label')
67+
ax.xaxis.set_ticks([])
68+
ax.yaxis.set_ticks([])
69+
plt.draw()
70+
71+
spine = ax.spines['left']
72+
spinebbox = spine.get_transform().transform_path(
73+
spine.get_path()).get_extents()
74+
# replace with assert_less if >python2.6
75+
assert_true(ax.yaxis.label.get_position()[0] < spinebbox.xmin,
76+
"Y-Axis label not left of the spine")
77+
78+
spine = ax.spines['bottom']
79+
spinebbox = spine.get_transform().transform_path(
80+
spine.get_path()).get_extents()
81+
# replace with assert_less if >python2.6
82+
assert_true(ax.xaxis.label.get_position()[1] < spinebbox.ymin,
83+
"X-Axis label not below the spine")

0 commit comments

Comments
 (0)