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

Skip to content

Commit f9e405e

Browse files
committed
Merge pull request #5682 from tacaswell/fix_twin_remove
Fix twin remove
2 parents 4a705d1 + f0a32b3 commit f9e405e

File tree

4 files changed

+122
-3
lines changed

4 files changed

+122
-3
lines changed

lib/matplotlib/cbook.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1669,7 +1669,7 @@ class Grouper(object):
16691669
False
16701670
16711671
"""
1672-
def __init__(self, init=[]):
1672+
def __init__(self, init=()):
16731673
mapping = self._mapping = {}
16741674
for x in init:
16751675
mapping[ref(x)] = [ref(x)]
@@ -1721,6 +1721,14 @@ def joined(self, a, b):
17211721
except KeyError:
17221722
return False
17231723

1724+
def remove(self, a):
1725+
self.clean()
1726+
1727+
mapping = self._mapping
1728+
seta = mapping.pop(ref(a), None)
1729+
if seta is not None:
1730+
seta.remove(ref(a))
1731+
17241732
def __iter__(self):
17251733
"""
17261734
Iterate over each of the disjoint sets as a list.

lib/matplotlib/figure.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,7 @@ def add_axes(self, *args, **kwargs):
916916

917917
self._axstack.add(key, a)
918918
self.sca(a)
919-
a._remove_method = lambda ax: self.delaxes(ax)
919+
a._remove_method = self.__remove_ax
920920
self.stale = True
921921
a.stale_callback = _stale_figure_callback
922922
return a
@@ -1006,11 +1006,37 @@ def add_subplot(self, *args, **kwargs):
10061006

10071007
self._axstack.add(key, a)
10081008
self.sca(a)
1009-
a._remove_method = lambda ax: self.delaxes(ax)
1009+
a._remove_method = self.__remove_ax
10101010
self.stale = True
10111011
a.stale_callback = _stale_figure_callback
10121012
return a
10131013

1014+
def __remove_ax(self, ax):
1015+
def _reset_loc_form(axis):
1016+
axis.set_major_formatter(axis.get_major_formatter())
1017+
axis.set_major_locator(axis.get_major_locator())
1018+
axis.set_minor_formatter(axis.get_minor_formatter())
1019+
axis.set_minor_locator(axis.get_minor_locator())
1020+
1021+
def _break_share_link(ax, grouper):
1022+
siblings = grouper.get_siblings(ax)
1023+
if len(siblings) > 1:
1024+
grouper.remove(ax)
1025+
for last_ax in siblings:
1026+
if ax is last_ax:
1027+
continue
1028+
return last_ax
1029+
return None
1030+
1031+
self.delaxes(ax)
1032+
last_ax = _break_share_link(ax, ax._shared_y_axes)
1033+
if last_ax is not None:
1034+
_reset_loc_form(last_ax.yaxis)
1035+
1036+
last_ax = _break_share_link(ax, ax._shared_x_axes)
1037+
if last_ax is not None:
1038+
_reset_loc_form(last_ax.xaxis)
1039+
10141040
def clf(self, keep_observers=False):
10151041
"""
10161042
Clear the figure.

lib/matplotlib/tests/test_axes.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4086,11 +4086,57 @@ def test_shared_scale():
40864086
assert_equal(ax.get_yscale(), 'linear')
40874087
assert_equal(ax.get_xscale(), 'linear')
40884088

4089+
40894090
@cleanup
40904091
def test_violin_point_mass():
40914092
"""Violin plot should handle point mass pdf gracefully."""
40924093
plt.violinplot(np.array([0, 0]))
40934094

4095+
4096+
@cleanup
4097+
def test_remove_shared_axes():
4098+
4099+
def _helper_x(ax):
4100+
ax2 = ax.twinx()
4101+
ax2.remove()
4102+
ax.set_xlim(0, 15)
4103+
r = ax.xaxis.get_major_locator()()
4104+
assert r[-1] > 14
4105+
4106+
def _helper_y(ax):
4107+
ax2 = ax.twiny()
4108+
ax2.remove()
4109+
ax.set_ylim(0, 15)
4110+
r = ax.yaxis.get_major_locator()()
4111+
assert r[-1] > 14
4112+
4113+
# test all of the ways to get fig/ax sets
4114+
fig = plt.figure()
4115+
ax = fig.gca()
4116+
yield _helper_x, ax
4117+
yield _helper_y, ax
4118+
4119+
fig, ax = plt.subplots()
4120+
yield _helper_x, ax
4121+
yield _helper_y, ax
4122+
4123+
fig, ax_lst = plt.subplots(2, 2, sharex='all', sharey='all')
4124+
ax = ax_lst[0][0]
4125+
yield _helper_x, ax
4126+
yield _helper_y, ax
4127+
4128+
fig = plt.figure()
4129+
ax = fig.add_axes([.1, .1, .8, .8])
4130+
yield _helper_x, ax
4131+
yield _helper_y, ax
4132+
4133+
fig, ax_lst = plt.subplots(2, 2, sharex='all', sharey='all')
4134+
ax = ax_lst[0][0]
4135+
orig_xlim = ax_lst[0][1].get_xlim()
4136+
ax.remove()
4137+
ax.set_xlim(0, 5)
4138+
assert assert_array_equal(ax_lst[0][1].get_xlim(), orig_xlim)
4139+
40944140
if __name__ == '__main__':
40954141
import nose
40964142
import sys

lib/matplotlib/tests/test_cbook.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import (absolute_import, division, print_function,
22
unicode_literals)
3+
import itertools
4+
from weakref import ref
35

46
from matplotlib.externals import six
57

@@ -376,3 +378,40 @@ def test_step_fails():
376378
np.arange(12))
377379
assert_raises(ValueError, cbook._step_validation,
378380
np.arange(12), np.arange(3))
381+
382+
383+
def test_grouper():
384+
class dummy():
385+
pass
386+
a, b, c, d, e = objs = [dummy() for j in range(5)]
387+
g = cbook.Grouper()
388+
g.join(*objs)
389+
assert set(list(g)[0]) == set(objs)
390+
assert set(g.get_siblings(a)) == set(objs)
391+
392+
for other in objs[1:]:
393+
assert g.joined(a, other)
394+
395+
g.remove(a)
396+
for other in objs[1:]:
397+
assert not g.joined(a, other)
398+
399+
for A, B in itertools.product(objs[1:], objs[1:]):
400+
assert g.joined(A, B)
401+
402+
403+
def test_grouper_private():
404+
class dummy():
405+
pass
406+
objs = [dummy() for j in range(5)]
407+
g = cbook.Grouper()
408+
g.join(*objs)
409+
# reach in and touch the internals !
410+
mapping = g._mapping
411+
412+
for o in objs:
413+
assert ref(o) in mapping
414+
415+
base_set = mapping[ref(objs[0])]
416+
for o in objs[1:]:
417+
assert mapping[ref(o)] is base_set

0 commit comments

Comments
 (0)