Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 69f704b

Browse files
committed
ENH: Move title if x-axis is on the top of the figure
1 parent 4af6392 commit 69f704b

File tree

7 files changed

+842
-5
lines changed

7 files changed

+842
-5
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Axes title will no longer overlap xaxis
2+
---------------------------------------
3+
4+
Previously the axes title had to be moved manually if an xaxis overlapped
5+
(usually when the xaxis was put on the top of the axes). The title can
6+
still be placed manaully.

examples/ticks_and_spines/tick_xlabel_top.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@
2222
fig, ax = plt.subplots()
2323

2424
ax.plot(x)
25-
ax.set_title('xlabel top', pad=24) # increase padding to make room for labels
25+
ax.set_title('xlabel top') # Note title moves to make room for ticks
2626

2727
plt.show()

lib/matplotlib/axes/_base.py

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from collections import OrderedDict
22
import itertools
3+
import logging
34
import math
45
from operator import attrgetter
56
import types
@@ -32,6 +33,8 @@
3233
from matplotlib.rcsetup import cycler
3334
from matplotlib.rcsetup import validate_axisbelow
3435

36+
_log = logging.getLogger(__name__)
37+
3538
rcParams = matplotlib.rcParams
3639

3740
_hold_msg = """axes.hold is deprecated.
@@ -1082,6 +1085,8 @@ def cla(self):
10821085
# refactor this out so it can be called in ax.set_title if
10831086
# pad argument used...
10841087
self._set_title_offset_trans(title_offset_points)
1088+
# determine if the title position has been set manually:
1089+
self._autotitlepos = None
10851090

10861091
for _title in (self.title, self._left_title, self._right_title):
10871092
self._set_artist_props(_title)
@@ -2512,6 +2517,50 @@ def handle_single_axis(scale, autoscaleon, shared_axes, interval,
25122517
def _get_axis_list(self):
25132518
return (self.xaxis, self.yaxis)
25142519

2520+
def _update_title_position(self, renderer):
2521+
"""
2522+
Update the title position based on the bounding box enclosing
2523+
all the ticklabels and x-axis spine and xlabel...
2524+
"""
2525+
_log.debug('update_title_pos')
2526+
2527+
if self._autotitlepos is not None and not self._autotitlepos:
2528+
_log.debug('title position was updated manually, not adjusting')
2529+
return
2530+
2531+
titles = (self.title, self._left_title, self._right_title)
2532+
2533+
if self._autotitlepos is None:
2534+
for title in titles:
2535+
x, y = title.get_position()
2536+
if not np.isclose(y, 1.0):
2537+
self._autotitlepos = False
2538+
_log.debug('not adjusting title pos because title was'
2539+
' already placed manually: %f', y)
2540+
return
2541+
self._autotitlepos = True
2542+
2543+
for title in titles:
2544+
x, y0 = title.get_position()
2545+
y = 1.0
2546+
# need to check all our twins too...
2547+
axs = self._twinned_axes.get_siblings(self)
2548+
2549+
for ax in axs:
2550+
try:
2551+
if (ax.xaxis.get_label_position() == 'top'
2552+
or ax.xaxis.get_ticks_position() == 'top'):
2553+
bb = ax.xaxis.get_tightbbox(renderer)
2554+
top = bb.y1
2555+
# we don't need to pad because the padding is already
2556+
# in __init__: titleOffsetTrans
2557+
yn = self.transAxes.inverted().transform((0., top))[1]
2558+
y = max(y, yn)
2559+
except AttributeError:
2560+
pass
2561+
2562+
title.set_position((x, y))
2563+
25152564
# Drawing
25162565

25172566
@allow_rasterization
@@ -2525,6 +2574,7 @@ def draw(self, renderer=None, inframe=False):
25252574
if not self.get_visible():
25262575
return
25272576
renderer.open_group('axes')
2577+
25282578
# prevent triggering call backs during the draw process
25292579
self._stale = True
25302580
locator = self.get_axes_locator()
@@ -2545,6 +2595,8 @@ def draw(self, renderer=None, inframe=False):
25452595
for spine in self.spines.values():
25462596
artists.remove(spine)
25472597

2598+
self._update_title_position(renderer)
2599+
25482600
if self.axison and not inframe:
25492601
if self._axisbelow is True:
25502602
self.xaxis.set_zorder(0.5)
@@ -2573,6 +2625,7 @@ def draw(self, renderer=None, inframe=False):
25732625
# rasterize artists with negative zorder
25742626
# if the minimum zorder is negative, start rasterization
25752627
rasterization_zorder = self._rasterization_zorder
2628+
25762629
if (rasterization_zorder is not None and
25772630
artists and artists[0].zorder < rasterization_zorder):
25782631
renderer.start_rasterizing()
@@ -2594,6 +2647,7 @@ def draw(self, renderer=None, inframe=False):
25942647
renderer.stop_rasterizing()
25952648

25962649
mimage._draw_list_compositing_images(renderer, self, artists)
2650+
self._update_title_position(renderer)
25972651

25982652
renderer.close_group('axes')
25992653
self._cachedRenderer = renderer
@@ -4117,6 +4171,12 @@ def get_tightbbox(self, renderer, call_axes_locator=True):
41174171
else:
41184172
self.apply_aspect()
41194173

4174+
bb_xaxis = self.xaxis.get_tightbbox(renderer)
4175+
if bb_xaxis:
4176+
bb.append(bb_xaxis)
4177+
4178+
self._update_title_position(renderer)
4179+
41204180
bb.append(self.get_window_extent(renderer))
41214181

41224182
if self.title.get_visible():
@@ -4126,10 +4186,6 @@ def get_tightbbox(self, renderer, call_axes_locator=True):
41264186
if self._right_title.get_visible():
41274187
bb.append(self._right_title.get_window_extent(renderer))
41284188

4129-
bb_xaxis = self.xaxis.get_tightbbox(renderer)
4130-
if bb_xaxis:
4131-
bb.append(bb_xaxis)
4132-
41334189
bb_yaxis = self.yaxis.get_tightbbox(renderer)
41344190
if bb_yaxis:
41354191
bb.append(bb_yaxis)
Binary file not shown.

0 commit comments

Comments
 (0)