From 8ac5b4b28edf27ddebaea364bf8b3e685e709c9e Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Fri, 18 Dec 2015 21:18:07 -0500 Subject: [PATCH] Merge pull request #5683 from mdboom/tight-ticks Include outward ticks in bounding box --- lib/matplotlib/axes/_base.py | 6 +- lib/matplotlib/axis.py | 32 +- .../test_tightlayout/outward_ticks.pdf | Bin 0 -> 2242 bytes .../test_tightlayout/outward_ticks.png | Bin 0 -> 6177 bytes .../test_tightlayout/outward_ticks.svg | 807 ++++++++++++++++++ lib/matplotlib/tests/test_tightlayout.py | 25 + 6 files changed, 863 insertions(+), 7 deletions(-) create mode 100644 lib/matplotlib/tests/baseline_images/test_tightlayout/outward_ticks.pdf create mode 100644 lib/matplotlib/tests/baseline_images/test_tightlayout/outward_ticks.png create mode 100644 lib/matplotlib/tests/baseline_images/test_tightlayout/outward_ticks.svg diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 6e7c40f554b5..de5d137d609e 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -567,7 +567,11 @@ def get_window_extent(self, *args, **kwargs): get the axes bounding box in display space; *args* and *kwargs* are empty """ - return self.bbox + bbox = self.bbox + x_pad = self.xaxis.get_tick_padding() + y_pad = self.yaxis.get_tick_padding() + return mtransforms.Bbox([[bbox.x0 - x_pad, bbox.y0 - y_pad], + [bbox.x1 + x_pad, bbox.y1 + y_pad]]) def _init_axis(self): "move this out of __init__ because non-separable axes don't use it" diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 0710eddf1154..e9f9f707e08d 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -169,6 +169,20 @@ def apply_tickdir(self, tickdir): """ pass + def get_tickdir(self): + return self._tickdir + + def get_tick_padding(self): + """ + Get the length of the tick outside of the axes. + """ + padding = { + 'in': 0.0, + 'inout': 0.5, + 'out': 1.0 + } + return self._size * padding[self._tickdir] + def get_children(self): children = [self.tick1line, self.tick2line, self.gridline, self.label1, self.label2] @@ -349,13 +363,11 @@ def apply_tickdir(self, tickdir): if self._tickdir == 'in': self._tickmarkers = (mlines.TICKUP, mlines.TICKDOWN) - self._pad = self._base_pad elif self._tickdir == 'inout': self._tickmarkers = ('|', '|') - self._pad = self._base_pad + self._size / 2. else: self._tickmarkers = (mlines.TICKDOWN, mlines.TICKUP) - self._pad = self._base_pad + self._size + self._pad = self._base_pad + self.get_tick_padding() self.stale = True def _get_text1(self): @@ -485,13 +497,11 @@ def apply_tickdir(self, tickdir): if self._tickdir == 'in': self._tickmarkers = (mlines.TICKRIGHT, mlines.TICKLEFT) - self._pad = self._base_pad elif self._tickdir == 'inout': self._tickmarkers = ('_', '_') - self._pad = self._base_pad + self._size / 2. else: self._tickmarkers = (mlines.TICKLEFT, mlines.TICKRIGHT) - self._pad = self._base_pad + self._size + self._pad = self._base_pad + self.get_tick_padding() self.stale = True # how far from the y axis line the right of the ticklabel are @@ -1095,6 +1105,16 @@ def get_tightbbox(self, renderer): else: return None + def get_tick_padding(self): + values = [] + if len(self.majorTicks): + values.append(self.majorTicks[0].get_tick_padding()) + if len(self.minorTicks): + values.append(self.minorTicks[0].get_tick_padding()) + if len(values): + return max(values) + return 0.0 + @allow_rasterization def draw(self, renderer, *args, **kwargs): 'Draw the axis lines, grid lines, tick lines and labels' diff --git a/lib/matplotlib/tests/baseline_images/test_tightlayout/outward_ticks.pdf b/lib/matplotlib/tests/baseline_images/test_tightlayout/outward_ticks.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7e0dd1ebcb58a4624e8a54bbc2e6cbdcf77b680c GIT binary patch literal 2242 zcmZ{m4OA0X7RTvYP-g8)-Qso?+gAk%3YnRFLeLgSAbcn&XpvxQC&?s)giJ^#X^f)P zs>sKxTS274%39RAQL11?EsFIhLeU~c5mD5xXDz7+N);DbcJ~dCg2m1`IWOtNS;&jZkR~8Xy?SOwcrGG64S2bhI2Cg9g_D!VLzBHpAWJ0F|03 zixDu#5+?yvLRz&-GEoYvfU~70!eBNMCeol>Lc0`7B+Zn?q=b?&nn20Kuza{~1|iHG8Ih1tb&P(@nycQ0q(MWc0i3x67$2q8 z!!yEB4<(h5N=h{pXr@ghk%8DsN{bo|H^U}JK6{R2t>^SytPEf8CO^K%t6ckuYFSzT zV7xxv*6`;WnSa`P*wM(Hvc#vZ0?m`}Nv=9`tZ5+qdUoHc4;FrHPgTS}9C-R#RR~()2~`-fqW@6>04uH7lpy&br(2 z{O}^@pmNvK?guS*?rclA^LF?3i|6P9M+s za!?!IbTQ6YaW?vyz5Hhq%ken5GFIGHkSm*0pIiTtsL;AS$P-FtV>qojwQf|X5<^$W_gkIWtnM%z^tKW;J? zMYHERdpA^;9$2T*)b3Lp%Dbf2e)xOgk!6#DE}b|WtW59JZ{IBUHmDzXDOP`djgBq; z&gF1)N5>(&E>&H{JF;m;+gue(SlKpH_2#3qqJ}(slB{4&!8DqE_oSk8MM@1fbxXh; z|IFs>Z3jKy&}OxIt-cqN$@?k44e1Lmt|mB_t&Ots)9;mdK0T*>oI{={IbXHwwOm=? zg4t_&cURp$DD$jTKMT!Qd)9w*zHjT*f0!p(E^JO+aVt!0XQf&LoH?IYIM?Jk%icNN z9#qh`)3HD*Z|R@b5A-(RCr8$x?p>ks z6g=Q){sei^X0N6C@PD(H$KCCdM^_(vG_d85`CWJYlUlkRy3V(@)I`_ZJ|itz zdx`hm+PZeD+p|p8Ioq2Nyq@z4cUvGbM>3Cnyz^BL&-yZi_dDK<=}$^8PpwQT)Vr|+ zPk!8}cCQaaFo}-M<7U=-`HDr8cy4bD_*~Apn5>yqO?2FQu)QSoz{5oczbdtsUdX-g ziE@{nExw7w-F#x*yz>tpF+29{ZWe89t1t+zr`slkO>aB*n%+C2%X(>5YTW&G9G5|# zGO2F5?+s?Lw}EX-@R-}Nde)VFA4gnWSJ2+DOB!Zaf354-gXg01n68djel`#Gs64-_ zjgZb(OjJ5-vRfytrewEU{Dyx`OCkPFKFs!so9wY<`%!UgT6c2jXMSN-tmZ3k>3BlN z%*#{DQVP;K|Ke@`TXMe7jtw&ugY|WK>hJ9alcb$pR>34i*L6Sv(f`T z&z8l8er(;KoA-Sr-~Cj@ehG6I@0aJ<5n7&*v$e0Z;*hk5_5HHQ()%9Gg_iz_z5coj z40cBVFaqEqS}+8`F`Vb3G6T&Ks*JLcfwBuV;rK8M!=VjT5&(B`ZGQGxCp_sBjw!&@Wv?_+-Lu5~6ushs}hP%_~>F^hVAtGtY z1XvjaZPZh=UaJ5&o6pABM#@YJ1;Tk60ZDRsYEB?XqiLfEMMpi^lt~kSps;zVEJ_IA zu}O?7HBb;r9TYzR5}w&cOBp0g&tpkM91Q2<99#&0Tucyz@%%B&KL8mm(qA`6!L#Xv^w?x literal 0 HcmV?d00001 diff --git a/lib/matplotlib/tests/baseline_images/test_tightlayout/outward_ticks.png b/lib/matplotlib/tests/baseline_images/test_tightlayout/outward_ticks.png new file mode 100644 index 0000000000000000000000000000000000000000..cc73be432858983bb2c64844fd6d796776b027f5 GIT binary patch literal 6177 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 x_hq+V;j>@db;U@Tv=R + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/matplotlib/tests/test_tightlayout.py b/lib/matplotlib/tests/test_tightlayout.py index 9d43242ed9f5..588f66dbae65 100644 --- a/lib/matplotlib/tests/test_tightlayout.py +++ b/lib/matplotlib/tests/test_tightlayout.py @@ -159,6 +159,31 @@ def test_tight_layout8(): example_plot(ax, fontsize=24) +@image_comparison(baseline_images=['outward_ticks'], remove_text=True) +def test_outward_ticks(): + 'Test automatic use of tight_layout' + fig = plt.figure() + ax = fig.add_subplot(221) + ax.xaxis.set_tick_params(tickdir='out', length=16, width=3) + ax.yaxis.set_tick_params(tickdir='out', length=16, width=3) + ax.xaxis.set_tick_params( + tickdir='out', length=32, width=3, tick1On=True, which='minor') + ax.yaxis.set_tick_params( + tickdir='out', length=32, width=3, tick1On=True, which='minor') + ax.xaxis.set_ticks([0], minor=True) + ax.yaxis.set_ticks([0], minor=True) + ax = fig.add_subplot(222) + ax.xaxis.set_tick_params(tickdir='in', length=32, width=3) + ax.yaxis.set_tick_params(tickdir='in', length=32, width=3) + ax = fig.add_subplot(223) + ax.xaxis.set_tick_params(tickdir='inout', length=32, width=3) + ax.yaxis.set_tick_params(tickdir='inout', length=32, width=3) + ax = fig.add_subplot(224) + ax.xaxis.set_tick_params(tickdir='out', length=32, width=3) + ax.yaxis.set_tick_params(tickdir='out', length=32, width=3) + plt.tight_layout() + + def add_offsetboxes(ax, size=10, margin=.1, color='black'): """ Surround ax with OffsetBoxes