@@ -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
@@ -156,6 +157,62 @@ def __contains__(self, a):
156
157
return a in self .as_list ()
157
158
158
159
160
+ class _AxesStack (object ):
161
+ """Lightweight stack that tracks Axes in a Figure.
162
+ """
163
+
164
+ def __init__ (self ):
165
+ # We maintain a list of (creation_index, key, axes) tuples.
166
+ # We do not use an OrderedDict because 1. the keys may not be hashable
167
+ # and 2. we need to directly find a pair corresponding to an axes (i.e.
168
+ # we'd really need a two-way dict).
169
+ self ._items = []
170
+ self ._created = 0
171
+
172
+ def as_list (self ):
173
+ """Copy of the list of axes, in the order of insertion.
174
+ """
175
+ return [ax for _ , _ , ax in sorted (self ._items )]
176
+
177
+ def get (self , key ):
178
+ """Find the axes corresponding to a key; defaults to `None`.
179
+ """
180
+ return next ((ax for _ , k , ax in self ._items if k == key ), None )
181
+
182
+ def current_key_axes (self ):
183
+ """Return the topmost `(key, axes)` pair, or `(None, None)` if empty.
184
+ """
185
+ _ , key , ax = (self ._items or [(None , None , None )])[- 1 ]
186
+ return key , ax
187
+
188
+ def add (self , key , ax ):
189
+ """Append a `(key, axes)` pair, unless the axes are already present.
190
+ """
191
+ # Skipping existing Axes is needed to support calling `add_axes` with
192
+ # an already existing Axes.
193
+ if not any (a == ax for _ , _ , a in self ._items ):
194
+ self ._items .append ((self ._created , key , ax ))
195
+ self ._created += 1
196
+
197
+ def bubble (self , ax ):
198
+ """Move an axes and its corresponding key to the top.
199
+ """
200
+ idx , = (idx for idx , (_ , _ , a ) in enumerate (self ._items ) if a == ax )
201
+ self ._items .append (self ._items [idx ])
202
+ del self ._items [idx ]
203
+
204
+ def remove (self , ax ):
205
+ """Remove an axes and its corresponding key.
206
+ """
207
+ idx , = (idx for idx , (_ , _ , a ) in enumerate (self ._items ) if a == ax )
208
+ del self ._items [idx ]
209
+
210
+ def clear (self ):
211
+ """Clear the stack.
212
+ """
213
+ del self ._items [:]
214
+
215
+
159
216
class SubplotParams (object ):
160
217
"""
161
218
A class to hold the parameters for a subplot
@@ -354,7 +411,7 @@ def __init__(self,
354
411
self .subplotpars = subplotpars
355
412
self .set_tight_layout (tight_layout )
356
413
357
- self ._axstack = AxesStack () # track all figure axes and current axes
414
+ self ._axstack = _AxesStack () # track all figure axes and current axes
358
415
self .clf ()
359
416
self ._cachedRenderer = None
360
417
@@ -402,10 +459,8 @@ def show(self, warn=True):
402
459
"matplotlib is currently using a non-GUI backend, "
403
460
"so cannot show the figure" )
404
461
405
- def _get_axes (self ):
406
- return self ._axstack .as_list ()
407
-
408
- axes = property (fget = _get_axes , doc = "Read-only: list of axes in Figure" )
462
+ axes = property (lambda self : self ._axstack .as_list (),
463
+ doc = "Read-only: list of axes in Figure" )
409
464
410
465
def _get_dpi (self ):
411
466
return self ._dpi
@@ -817,36 +872,6 @@ def delaxes(self, a):
817
872
func (self )
818
873
self .stale = True
819
874
820
- def _make_key (self , * args , ** kwargs ):
821
- 'make a hashable key out of args and kwargs'
822
-
823
- def fixitems (items ):
824
- #items may have arrays and lists in them, so convert them
825
- # to tuples for the key
826
- ret = []
827
- for k , v in items :
828
- # some objects can define __getitem__ without being
829
- # iterable and in those cases the conversion to tuples
830
- # will fail. So instead of using the iterable(v) function
831
- # we simply try and convert to a tuple, and proceed if not.
832
- try :
833
- v = tuple (v )
834
- except Exception :
835
- pass
836
- ret .append ((k , v ))
837
- return tuple (ret )
838
-
839
- def fixlist (args ):
840
- ret = []
841
- for a in args :
842
- if iterable (a ):
843
- a = tuple (a )
844
- ret .append (a )
845
- return tuple (ret )
846
-
847
- key = fixlist (args ), fixitems (six .iteritems (kwargs ))
848
- return key
849
-
850
875
@docstring .dedent_interpd
851
876
def add_axes (self , * args , ** kwargs ):
852
877
"""
@@ -900,9 +925,9 @@ def add_axes(self, *args, **kwargs):
900
925
901
926
# shortcut the projection "key" modifications later on, if an axes
902
927
# with the exact args/kwargs exists, return it immediately.
903
- key = self . _make_key ( * args , ** kwargs )
928
+ key = ( args , kwargs )
904
929
ax = self ._axstack .get (key )
905
- if ax is not None :
930
+ if ax :
906
931
self .sca (ax )
907
932
return ax
908
933
@@ -919,7 +944,7 @@ def add_axes(self, *args, **kwargs):
919
944
# check that an axes of this type doesn't already exist, if it
920
945
# does, set it as active and return it
921
946
ax = self ._axstack .get (key )
922
- if ax is not None and isinstance (ax , projection_class ):
947
+ if isinstance (ax , projection_class ):
923
948
self .sca (ax )
924
949
return ax
925
950
@@ -993,15 +1018,14 @@ def add_subplot(self, *args, **kwargs):
993
1018
raise ValueError (msg )
994
1019
# make a key for the subplot (which includes the axes object id
995
1020
# in the hash)
996
- key = self . _make_key ( * args , ** kwargs )
1021
+ key = ( args , kwargs )
997
1022
else :
998
1023
projection_class , kwargs , key = process_projection_requirements (
999
1024
self , * args , ** kwargs )
1000
1025
1001
1026
# try to find the axes with this key in the stack
1002
1027
ax = self ._axstack .get (key )
1003
-
1004
- if ax is not None :
1028
+ if ax :
1005
1029
if isinstance (ax , projection_class ):
1006
1030
# the axes already existed, so set it as active & return
1007
1031
self .sca (ax )
@@ -1483,7 +1507,7 @@ def _gci(self):
1483
1507
do not use elsewhere.
1484
1508
"""
1485
1509
# Look first for an image in the current Axes:
1486
- cax = self ._axstack .current_key_axes ()[ 1 ]
1510
+ ckey , cax = self ._axstack .current_key_axes ()
1487
1511
if cax is None :
1488
1512
return None
1489
1513
im = cax ._gci ()
0 commit comments