1414the Quiver code.
1515"""
1616
17-
1817from __future__ import (absolute_import , division , print_function ,
1918 unicode_literals )
2019
2120import six
21+ import weakref
2222
2323import numpy as np
2424from numpy import ma
25- import matplotlib .collections as collections
25+ import matplotlib .collections as mcollections
2626import matplotlib .transforms as transforms
2727import matplotlib .text as mtext
2828import matplotlib .artist as martist
223223
224224class QuiverKey (martist .Artist ):
225225 """ Labelled arrow for use as a quiver plot scale key."""
226- halign = {'N' : 'center' , 'S' : 'center' , 'E' : 'left' , 'W' : 'right' }
227- valign = {'N' : 'bottom' , 'S' : 'top' , 'E' : 'center' , 'W' : 'center' }
228- pivot = {'N' : 'mid' , 'S' : 'mid' , 'E' : 'tip' , 'W' : 'tail' }
226+ halign = {'N' : 'center' , 'S' : 'center' , 'E' : 'left' , 'W' : 'right' }
227+ valign = {'N' : 'bottom' , 'S' : 'top' , 'E' : 'center' , 'W' : 'center' }
228+ pivot = {'N' : 'mid' , 'S' : 'mid' , 'E' : 'tip' , 'W' : 'tail' }
229229
230230 def __init__ (self , Q , X , Y , U , label , ** kw ):
231231 martist .Artist .__init__ (self )
@@ -239,13 +239,19 @@ def __init__(self, Q, X, Y, U, label, **kw):
239239 self ._labelsep_inches = kw .pop ('labelsep' , 0.1 )
240240 self .labelsep = (self ._labelsep_inches * Q .ax .figure .dpi )
241241
242+ # try to prevent closure over the real self
243+ weak_self = weakref .ref (self )
244+
242245 def on_dpi_change (fig ):
243- self .labelsep = (self ._labelsep_inches * fig .dpi )
244- self ._initialized = False # simple brute force update
245- # works because _init is called
246- # at the start of draw.
246+ self_weakref = weak_self ()
247+ if self_weakref is not None :
248+ self_weakref .labelsep = (self_weakref ._labelsep_inches * fig .dpi )
249+ self_weakref ._initialized = False # simple brute force update
250+ # works because _init is called
251+ # at the start of draw.
247252
248- Q .ax .figure .callbacks .connect ('dpi_changed' , on_dpi_change )
253+ self ._cid = Q .ax .figure .callbacks .connect ('dpi_changed' ,
254+ on_dpi_change )
249255
250256 self .labelpos = kw .pop ('labelpos' , 'N' )
251257 self .labelcolor = kw .pop ('labelcolor' , None )
@@ -258,11 +264,21 @@ def on_dpi_change(fig):
258264 horizontalalignment = self .halign [self .labelpos ],
259265 verticalalignment = self .valign [self .labelpos ],
260266 fontproperties = font_manager .FontProperties (** _fp ))
267+
261268 if self .labelcolor is not None :
262269 self .text .set_color (self .labelcolor )
263270 self ._initialized = False
264271 self .zorder = Q .zorder + 0.1
265272
273+ def remove (self ):
274+ """
275+ Overload the remove method
276+ """
277+ self .Q .ax .figure .callbacks .disconnect (self ._cid )
278+ self ._cid = None
279+ # pass the remove call up the stack
280+ martist .Artist .remove (self )
281+
266282 __init__ .__doc__ = _quiverkey_doc
267283
268284 def _init (self ):
@@ -279,7 +295,7 @@ def _init(self):
279295 self .Q .pivot = _pivot
280296 kw = self .Q .polykw
281297 kw .update (self .kw )
282- self .vector = collections .PolyCollection (
298+ self .vector = mcollections .PolyCollection (
283299 self .verts ,
284300 offsets = [(self .X , self .Y )],
285301 transOffset = self .get_transform (),
@@ -368,7 +384,7 @@ def _parse_args(*args):
368384 return X , Y , U , V , C
369385
370386
371- class Quiver (collections .PolyCollection ):
387+ class Quiver (mcollections .PolyCollection ):
372388 """
373389 Specialized PolyCollection for arrows.
374390
@@ -415,7 +431,7 @@ def __init__(self, ax, *args, **kw):
415431 self .transform = kw .pop ('transform' , ax .transData )
416432 kw .setdefault ('facecolors' , self .color )
417433 kw .setdefault ('linewidths' , (0 ,))
418- collections .PolyCollection .__init__ (self , [], offsets = self .XY ,
434+ mcollections .PolyCollection .__init__ (self , [], offsets = self .XY ,
419435 transOffset = self .transform ,
420436 closed = False ,
421437 ** kw )
@@ -426,14 +442,30 @@ def __init__(self, ax, *args, **kw):
426442 self .keyvec = None
427443 self .keytext = None
428444
429- def on_dpi_change (fig ):
430- self ._new_UV = True # vertices depend on width, span
431- # which in turn depend on dpi
432- self ._initialized = False # simple brute force update
433- # works because _init is called
434- # at the start of draw.
445+ # try to prevent closure over the real self
446+ weak_self = weakref .ref (self )
435447
436- self .ax .figure .callbacks .connect ('dpi_changed' , on_dpi_change )
448+ def on_dpi_change (fig ):
449+ self_weakref = weak_self ()
450+ if self_weakref is not None :
451+ self_weakref ._new_UV = True # vertices depend on width, span
452+ # which in turn depend on dpi
453+ self_weakref ._initialized = False # simple brute force update
454+ # works because _init is called
455+ # at the start of draw.
456+
457+ self ._cid = self .ax .figure .callbacks .connect ('dpi_changed' ,
458+ on_dpi_change )
459+
460+ def remove (self ):
461+ """
462+ Overload the remove method
463+ """
464+ # disconnect the call back
465+ self .ax .figure .callbacks .disconnect (self ._cid )
466+ self ._cid = None
467+ # pass the remove call up the stack
468+ mcollections .PolyCollection .remove (self )
437469
438470 def _init (self ):
439471 """
@@ -460,7 +492,7 @@ def draw(self, renderer):
460492 verts = self ._make_verts (self .U , self .V )
461493 self .set_verts (verts , closed = False )
462494 self ._new_UV = False
463- collections .PolyCollection .draw (self , renderer )
495+ mcollections .PolyCollection .draw (self , renderer )
464496
465497 def set_UVC (self , U , V , C = None ):
466498 U = ma .masked_invalid (U , copy = False ).ravel ()
@@ -793,7 +825,7 @@ def _h_arrows(self, length):
793825docstring .interpd .update (barbs_doc = _barbs_doc )
794826
795827
796- class Barbs (collections .PolyCollection ):
828+ class Barbs (mcollections .PolyCollection ):
797829 '''
798830 Specialized PolyCollection for barbs.
799831
@@ -854,8 +886,9 @@ def __init__(self, ax, *args, **kw):
854886
855887 #Make a collection
856888 barb_size = self ._length ** 2 / 4 # Empirically determined
857- collections .PolyCollection .__init__ (self , [], (barb_size ,), offsets = xy ,
858- transOffset = transform , ** kw )
889+ mcollections .PolyCollection .__init__ (self , [], (barb_size ,),
890+ offsets = xy ,
891+ transOffset = transform , ** kw )
859892 self .set_transform (transforms .IdentityTransform ())
860893
861894 self .set_UVC (u , v , c )
@@ -1078,7 +1111,7 @@ def set_offsets(self, xy):
10781111 x , y , u , v = delete_masked_points (self .x .ravel (), self .y .ravel (),
10791112 self .u , self .v )
10801113 xy = np .hstack ((x [:, np .newaxis ], y [:, np .newaxis ]))
1081- collections .PolyCollection .set_offsets (self , xy )
1082- set_offsets .__doc__ = collections .PolyCollection .set_offsets .__doc__
1114+ mcollections .PolyCollection .set_offsets (self , xy )
1115+ set_offsets .__doc__ = mcollections .PolyCollection .set_offsets .__doc__
10831116
10841117 barbs_doc = _barbs_doc
0 commit comments