@@ -72,7 +72,6 @@ class AxesStack(Stack):
7272
7373 """
7474 def __init__ (self ):
75- cbook .warn_deprecated ("2.1" )
7675 Stack .__init__ (self )
7776 self ._ind = 0
7877
@@ -92,6 +91,13 @@ def get(self, key):
9291 item = dict (self ._elements ).get (key )
9392 if item is None :
9493 return None
94+ cbook .warn_deprecated (
95+ "2.1" ,
96+ "Adding an axes using the same arguments as a previous axes "
97+ "currently reuses the earlier instance. In a future version, "
98+ "a new instance will always be created and returned. Meanwhile, "
99+ "this warning can be suppressed, and the future behavior ensured, "
100+ "by passing a unique label to each axes instance." )
95101 return item [1 ]
96102
97103 def _entry_from_axes (self , e ):
@@ -159,62 +165,6 @@ def __contains__(self, a):
159165 return a in self .as_list ()
160166
161167
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-
218168class SubplotParams (object ):
219169 """
220170 A class to hold the parameters for a subplot
@@ -415,7 +365,7 @@ def __init__(self,
415365 self .subplotpars = subplotpars
416366 self .set_tight_layout (tight_layout )
417367
418- self ._axstack = _AxesStack () # track all figure axes and current axes
368+ self ._axstack = AxesStack () # track all figure axes and current axes
419369 self .clf ()
420370 self ._cachedRenderer = None
421371
@@ -467,8 +417,10 @@ def show(self, warn=True):
467417 "matplotlib is currently using a non-GUI backend, "
468418 "so cannot show the figure" )
469419
470- axes = property (lambda self : self ._axstack .as_list (),
471- doc = "Read-only: list of axes in Figure" )
420+ def _get_axes (self ):
421+ return self ._axstack .as_list ()
422+
423+ axes = property (fget = _get_axes , doc = "Read-only: list of axes in Figure" )
472424
473425 def _get_dpi (self ):
474426 return self ._dpi
@@ -890,6 +842,36 @@ def delaxes(self, a):
890842 func (self )
891843 self .stale = True
892844
845+ def _make_key (self , * args , ** kwargs ):
846+ 'make a hashable key out of args and kwargs'
847+
848+ def fixitems (items ):
849+ #items may have arrays and lists in them, so convert them
850+ # to tuples for the key
851+ ret = []
852+ for k , v in items :
853+ # some objects can define __getitem__ without being
854+ # iterable and in those cases the conversion to tuples
855+ # will fail. So instead of using the iterable(v) function
856+ # we simply try and convert to a tuple, and proceed if not.
857+ try :
858+ v = tuple (v )
859+ except Exception :
860+ pass
861+ ret .append ((k , v ))
862+ return tuple (ret )
863+
864+ def fixlist (args ):
865+ ret = []
866+ for a in args :
867+ if iterable (a ):
868+ a = tuple (a )
869+ ret .append (a )
870+ return tuple (ret )
871+
872+ key = fixlist (args ), fixitems (six .iteritems (kwargs ))
873+ return key
874+
893875 def add_axes (self , * args , ** kwargs ):
894876 """
895877 Add an axes at position *rect* [*left*, *bottom*, *width*,
@@ -926,14 +908,14 @@ def add_axes(self, *args, **kwargs):
926908 fig.add_axes(rect, projection='polar')
927909 fig.add_axes(ax)
928910
929- If the figure already has an axes with the same parameters,
930- then it will simply make that axes current and return it. If
931- you do not want this behavior, e.g., you want to force the
932- creation of a new Axes , you must use a unique set of args and
933- kwargs. The axes :attr:`~matplotlib.axes.Axes.label`
934- attribute has been exposed for this purpose. e.g., if you want
935- two axes that are otherwise identical to be added to the
936- figure, make sure you give them unique labels::
911+ If the figure already has an axes with the same parameters, then it
912+ will simply make that axes current and return it. This behavior
913+ has been deprecated as of Matplotlib 2.1. Meanwhile, if you do
914+ not want this behavior (i.e. , you want to force the creation of a
915+ new Axes), you must use a unique set of args and kwargs. The axes
916+ :attr:`~matplotlib.axes.Axes.label` attribute has been exposed for this
917+ purpose: if you want two axes that are otherwise identical to be added
918+ to the figure, make sure you give them unique labels::
937919
938920 fig.add_axes(rect, label='axes1')
939921 fig.add_axes(rect, label='axes2')
@@ -954,9 +936,9 @@ def add_axes(self, *args, **kwargs):
954936
955937 # shortcut the projection "key" modifications later on, if an axes
956938 # with the exact args/kwargs exists, return it immediately.
957- key = ( args , kwargs )
939+ key = self . _make_key ( * args , ** kwargs )
958940 ax = self ._axstack .get (key )
959- if ax :
941+ if ax is not None :
960942 self .sca (ax )
961943 return ax
962944
@@ -976,7 +958,7 @@ def add_axes(self, *args, **kwargs):
976958 # check that an axes of this type doesn't already exist, if it
977959 # does, set it as active and return it
978960 ax = self ._axstack .get (key )
979- if isinstance (ax , projection_class ):
961+ if ax is not None and isinstance (ax , projection_class ):
980962 self .sca (ax )
981963 return ax
982964
@@ -1021,14 +1003,14 @@ def add_subplot(self, *args, **kwargs):
10211003 -----
10221004 If the figure already has a subplot with key (*args*,
10231005 *kwargs*) then it will simply make that subplot current and
1024- return it.
1006+ return it. This behavior is deprecated.
10251007
10261008 Examples
10271009 --------
10281010 fig.add_subplot(111)
10291011
10301012 # equivalent but more general
1031- fig.add_subplot(1,1, 1)
1013+ fig.add_subplot(1, 1, 1)
10321014
10331015 # add subplot with red background
10341016 fig.add_subplot(212, facecolor='r')
@@ -1047,29 +1029,29 @@ def add_subplot(self, *args, **kwargs):
10471029 return
10481030
10491031 if len (args ) == 1 and isinstance (args [0 ], int ):
1050- args = tuple ([int (c ) for c in str (args [0 ])])
1051- if len (args ) != 3 :
1052- raise ValueError ("Integer subplot specification must " +
1053- "be a three digit number. " +
1054- "Not {n:d}" .format (n = len (args )))
1032+ if not 100 <= args [0 ] <= 999 :
1033+ raise ValueError ("Integer subplot specification must be a "
1034+ "three-digit number, not {}" .format (args [0 ]))
1035+ args = tuple (map (int , str (args [0 ])))
10551036
10561037 if isinstance (args [0 ], SubplotBase ):
10571038
10581039 a = args [0 ]
10591040 if a .get_figure () is not self :
1060- msg = ("The Subplot must have been created in the present"
1061- " figure" )
1041+ msg = ("The Subplot must have been created in the present "
1042+ "figure" )
10621043 raise ValueError (msg )
10631044 # make a key for the subplot (which includes the axes object id
10641045 # in the hash)
1065- key = ( args , kwargs )
1046+ key = self . _make_key ( * args , ** kwargs )
10661047 else :
10671048 projection_class , kwargs , key = process_projection_requirements (
10681049 self , * args , ** kwargs )
10691050
10701051 # try to find the axes with this key in the stack
10711052 ax = self ._axstack .get (key )
1072- if ax :
1053+
1054+ if ax is not None :
10731055 if isinstance (ax , projection_class ):
10741056 # the axes already existed, so set it as active & return
10751057 self .sca (ax )
@@ -1638,7 +1620,7 @@ def _gci(self):
16381620 do not use elsewhere.
16391621 """
16401622 # Look first for an image in the current Axes:
1641- ckey , cax = self ._axstack .current_key_axes ()
1623+ cax = self ._axstack .current_key_axes ()[ 1 ]
16421624 if cax is None :
16431625 return None
16441626 im = cax ._gci ()
0 commit comments