@@ -72,6 +72,7 @@ class AxesStack(Stack):
72
72
73
73
"""
74
74
def __init__ (self ):
75
+ cbook .warn_deprecated ("2.1" )
75
76
Stack .__init__ (self )
76
77
self ._ind = 0
77
78
@@ -158,6 +159,62 @@ def __contains__(self, a):
158
159
return a in self .as_list ()
159
160
160
161
162
+ class _AxesStack (object ):
163
+ """Lightweight stack that tracks Axes in a Figure.
164
+ """
165
+
166
+ def __init__ (self ):
167
+ # We maintain a list of (creation_index, key, axes) tuples.
168
+ # We do not use an OrderedDict because 1. the keys may not be hashable
169
+ # and 2. we need to directly find a pair corresponding to an axes (i.e.
170
+ # we'd really need a two-way dict).
171
+ self ._items = []
172
+ self ._created = 0
173
+
174
+ def as_list (self ):
175
+ """Copy of the list of axes, in the order of insertion.
176
+ """
177
+ return [ax for _ , _ , ax in sorted (self ._items )]
178
+
179
+ def get (self , key ):
180
+ """Find the axes corresponding to a key; defaults to `None`.
181
+ """
182
+ return next ((ax for _ , k , ax in self ._items if k == key ), None )
183
+
184
+ def current_key_axes (self ):
185
+ """Return the topmost `(key, axes)` pair, or `(None, None)` if empty.
186
+ """
187
+ _ , key , ax = (self ._items or [(None , None , None )])[- 1 ]
188
+ return key , ax
189
+
190
+ def add (self , key , ax ):
191
+ """Append a `(key, axes)` pair, unless the axes are already present.
192
+ """
193
+ # Skipping existing Axes is needed to support calling `add_axes` with
194
+ # an already existing Axes.
195
+ if not any (a == ax for _ , _ , a in self ._items ):
196
+ self ._items .append ((self ._created , key , ax ))
197
+ self ._created += 1
198
+
199
+ def bubble (self , ax ):
200
+ """Move an axes and its corresponding key to the top.
201
+ """
202
+ idx , = (idx for idx , (_ , _ , a ) in enumerate (self ._items ) if a == ax )
203
+ self ._items .append (self ._items [idx ])
204
+ del self ._items [idx ]
205
+
206
+ def remove (self , ax ):
207
+ """Remove an axes and its corresponding key.
208
+ """
209
+ idx , = (idx for idx , (_ , _ , a ) in enumerate (self ._items ) if a == ax )
210
+ del self ._items [idx ]
211
+
212
+ def clear (self ):
213
+ """Clear the stack.
214
+ """
215
+ del self ._items [:]
216
+
217
+
161
218
class SubplotParams (object ):
162
219
"""
163
220
A class to hold the parameters for a subplot
@@ -358,7 +415,7 @@ def __init__(self,
358
415
self .subplotpars = subplotpars
359
416
self .set_tight_layout (tight_layout )
360
417
361
- self ._axstack = AxesStack () # track all figure axes and current axes
418
+ self ._axstack = _AxesStack () # track all figure axes and current axes
362
419
self .clf ()
363
420
self ._cachedRenderer = None
364
421
@@ -410,10 +467,8 @@ def show(self, warn=True):
410
467
"matplotlib is currently using a non-GUI backend, "
411
468
"so cannot show the figure" )
412
469
413
- def _get_axes (self ):
414
- return self ._axstack .as_list ()
415
-
416
- axes = property (fget = _get_axes , doc = "Read-only: list of axes in Figure" )
470
+ axes = property (lambda self : self ._axstack .as_list (),
471
+ doc = "Read-only: list of axes in Figure" )
417
472
418
473
def _get_dpi (self ):
419
474
return self ._dpi
@@ -835,36 +890,6 @@ def delaxes(self, a):
835
890
func (self )
836
891
self .stale = True
837
892
838
- def _make_key (self , * args , ** kwargs ):
839
- 'make a hashable key out of args and kwargs'
840
-
841
- def fixitems (items ):
842
- #items may have arrays and lists in them, so convert them
843
- # to tuples for the key
844
- ret = []
845
- for k , v in items :
846
- # some objects can define __getitem__ without being
847
- # iterable and in those cases the conversion to tuples
848
- # will fail. So instead of using the iterable(v) function
849
- # we simply try and convert to a tuple, and proceed if not.
850
- try :
851
- v = tuple (v )
852
- except Exception :
853
- pass
854
- ret .append ((k , v ))
855
- return tuple (ret )
856
-
857
- def fixlist (args ):
858
- ret = []
859
- for a in args :
860
- if iterable (a ):
861
- a = tuple (a )
862
- ret .append (a )
863
- return tuple (ret )
864
-
865
- key = fixlist (args ), fixitems (six .iteritems (kwargs ))
866
- return key
867
-
868
893
def add_axes (self , * args , ** kwargs ):
869
894
"""
870
895
Add an axes at position *rect* [*left*, *bottom*, *width*,
@@ -929,9 +954,9 @@ def add_axes(self, *args, **kwargs):
929
954
930
955
# shortcut the projection "key" modifications later on, if an axes
931
956
# with the exact args/kwargs exists, return it immediately.
932
- key = self . _make_key ( * args , ** kwargs )
957
+ key = ( args , kwargs )
933
958
ax = self ._axstack .get (key )
934
- if ax is not None :
959
+ if ax :
935
960
self .sca (ax )
936
961
return ax
937
962
@@ -951,7 +976,7 @@ def add_axes(self, *args, **kwargs):
951
976
# check that an axes of this type doesn't already exist, if it
952
977
# does, set it as active and return it
953
978
ax = self ._axstack .get (key )
954
- if ax is not None and isinstance (ax , projection_class ):
979
+ if isinstance (ax , projection_class ):
955
980
self .sca (ax )
956
981
return ax
957
982
@@ -1037,15 +1062,14 @@ def add_subplot(self, *args, **kwargs):
1037
1062
raise ValueError (msg )
1038
1063
# make a key for the subplot (which includes the axes object id
1039
1064
# in the hash)
1040
- key = self . _make_key ( * args , ** kwargs )
1065
+ key = ( args , kwargs )
1041
1066
else :
1042
1067
projection_class , kwargs , key = process_projection_requirements (
1043
1068
self , * args , ** kwargs )
1044
1069
1045
1070
# try to find the axes with this key in the stack
1046
1071
ax = self ._axstack .get (key )
1047
-
1048
- if ax is not None :
1072
+ if ax :
1049
1073
if isinstance (ax , projection_class ):
1050
1074
# the axes already existed, so set it as active & return
1051
1075
self .sca (ax )
@@ -1614,7 +1638,7 @@ def _gci(self):
1614
1638
do not use elsewhere.
1615
1639
"""
1616
1640
# Look first for an image in the current Axes:
1617
- cax = self ._axstack .current_key_axes ()[ 1 ]
1641
+ ckey , cax = self ._axstack .current_key_axes ()
1618
1642
if cax is None :
1619
1643
return None
1620
1644
im = cax ._gci ()
0 commit comments