1414the Quiver code.
1515"""
1616
17-
1817from __future__ import print_function , division
18+ import weakref
19+
1920import numpy as np
2021from numpy import ma
21- import matplotlib .collections as collections
22+ import matplotlib .collections as mcollections
2223import matplotlib .transforms as transforms
2324import matplotlib .text as mtext
2425import matplotlib .artist as martist
219220
220221class QuiverKey (martist .Artist ):
221222 """ Labelled arrow for use as a quiver plot scale key."""
222- halign = {'N' : 'center' , 'S' : 'center' , 'E' : 'left' , 'W' : 'right' }
223- valign = {'N' : 'bottom' , 'S' : 'top' , 'E' : 'center' , 'W' : 'center' }
224- pivot = {'N' : 'mid' , 'S' : 'mid' , 'E' : 'tip' , 'W' : 'tail' }
223+ halign = {'N' : 'center' , 'S' : 'center' , 'E' : 'left' , 'W' : 'right' }
224+ valign = {'N' : 'bottom' , 'S' : 'top' , 'E' : 'center' , 'W' : 'center' }
225+ pivot = {'N' : 'mid' , 'S' : 'mid' , 'E' : 'tip' , 'W' : 'tail' }
225226
226227 def __init__ (self , Q , X , Y , U , label , ** kw ):
227228 martist .Artist .__init__ (self )
@@ -235,13 +236,19 @@ def __init__(self, Q, X, Y, U, label, **kw):
235236 self ._labelsep_inches = kw .pop ('labelsep' , 0.1 )
236237 self .labelsep = (self ._labelsep_inches * Q .ax .figure .dpi )
237238
239+ # try to prevent closure over the real self
240+ weak_self = weakref .ref (self )
241+
238242 def on_dpi_change (fig ):
239- self .labelsep = (self ._labelsep_inches * fig .dpi )
240- self ._initialized = False # simple brute force update
241- # works because _init is called
242- # at the start of draw.
243+ self_weakref = weak_self ()
244+ if self_weakref is not None :
245+ self_weakref .labelsep = (self_weakref ._labelsep_inches * fig .dpi )
246+ self_weakref ._initialized = False # simple brute force update
247+ # works because _init is called
248+ # at the start of draw.
243249
244- Q .ax .figure .callbacks .connect ('dpi_changed' , on_dpi_change )
250+ self ._cid = Q .ax .figure .callbacks .connect ('dpi_changed' ,
251+ on_dpi_change )
245252
246253 self .labelpos = kw .pop ('labelpos' , 'N' )
247254 self .labelcolor = kw .pop ('labelcolor' , None )
@@ -254,11 +261,21 @@ def on_dpi_change(fig):
254261 horizontalalignment = self .halign [self .labelpos ],
255262 verticalalignment = self .valign [self .labelpos ],
256263 fontproperties = font_manager .FontProperties (** _fp ))
264+
257265 if self .labelcolor is not None :
258266 self .text .set_color (self .labelcolor )
259267 self ._initialized = False
260268 self .zorder = Q .zorder + 0.1
261269
270+ def remove (self ):
271+ """
272+ Overload the remove method
273+ """
274+ self .Q .ax .figure .callbacks .disconnect (self ._cid )
275+ self ._cid = None
276+ # pass the remove call up the stack
277+ martist .Artist .remove (self )
278+
262279 __init__ .__doc__ = _quiverkey_doc
263280
264281 def _init (self ):
@@ -275,7 +292,7 @@ def _init(self):
275292 self .Q .pivot = _pivot
276293 kw = self .Q .polykw
277294 kw .update (self .kw )
278- self .vector = collections .PolyCollection (
295+ self .vector = mcollections .PolyCollection (
279296 self .verts ,
280297 offsets = [(self .X , self .Y )],
281298 transOffset = self .get_transform (),
@@ -364,7 +381,7 @@ def _parse_args(*args):
364381 return X , Y , U , V , C
365382
366383
367- class Quiver (collections .PolyCollection ):
384+ class Quiver (mcollections .PolyCollection ):
368385 """
369386 Specialized PolyCollection for arrows.
370387
@@ -411,7 +428,7 @@ def __init__(self, ax, *args, **kw):
411428 self .transform = kw .pop ('transform' , ax .transData )
412429 kw .setdefault ('facecolors' , self .color )
413430 kw .setdefault ('linewidths' , (0 ,))
414- collections .PolyCollection .__init__ (self , [], offsets = self .XY ,
431+ mcollections .PolyCollection .__init__ (self , [], offsets = self .XY ,
415432 transOffset = self .transform ,
416433 closed = False ,
417434 ** kw )
@@ -422,14 +439,30 @@ def __init__(self, ax, *args, **kw):
422439 self .keyvec = None
423440 self .keytext = None
424441
425- def on_dpi_change (fig ):
426- self ._new_UV = True # vertices depend on width, span
427- # which in turn depend on dpi
428- self ._initialized = False # simple brute force update
429- # works because _init is called
430- # at the start of draw.
442+ # try to prevent closure over the real self
443+ weak_self = weakref .ref (self )
431444
432- self .ax .figure .callbacks .connect ('dpi_changed' , on_dpi_change )
445+ def on_dpi_change (fig ):
446+ self_weakref = weak_self ()
447+ if self_weakref is not None :
448+ self_weakref ._new_UV = True # vertices depend on width, span
449+ # which in turn depend on dpi
450+ self_weakref ._initialized = False # simple brute force update
451+ # works because _init is called
452+ # at the start of draw.
453+
454+ self ._cid = self .ax .figure .callbacks .connect ('dpi_changed' ,
455+ on_dpi_change )
456+
457+ def remove (self ):
458+ """
459+ Overload the remove method
460+ """
461+ # disconnect the call back
462+ self .ax .figure .callbacks .disconnect (self ._cid )
463+ self ._cid = None
464+ # pass the remove call up the stack
465+ mcollections .PolyCollection .remove (self )
433466
434467 def _init (self ):
435468 """
@@ -456,7 +489,7 @@ def draw(self, renderer):
456489 verts = self ._make_verts (self .U , self .V )
457490 self .set_verts (verts , closed = False )
458491 self ._new_UV = False
459- collections .PolyCollection .draw (self , renderer )
492+ mcollections .PolyCollection .draw (self , renderer )
460493
461494 def set_UVC (self , U , V , C = None ):
462495 U = ma .masked_invalid (U , copy = False ).ravel ()
@@ -789,7 +822,7 @@ def _h_arrows(self, length):
789822docstring .interpd .update (barbs_doc = _barbs_doc )
790823
791824
792- class Barbs (collections .PolyCollection ):
825+ class Barbs (mcollections .PolyCollection ):
793826 '''
794827 Specialized PolyCollection for barbs.
795828
@@ -850,8 +883,9 @@ def __init__(self, ax, *args, **kw):
850883
851884 #Make a collection
852885 barb_size = self ._length ** 2 / 4 # Empirically determined
853- collections .PolyCollection .__init__ (self , [], (barb_size ,), offsets = xy ,
854- transOffset = transform , ** kw )
886+ mcollections .PolyCollection .__init__ (self , [], (barb_size ,),
887+ offsets = xy ,
888+ transOffset = transform , ** kw )
855889 self .set_transform (transforms .IdentityTransform ())
856890
857891 self .set_UVC (u , v , c )
@@ -1074,7 +1108,7 @@ def set_offsets(self, xy):
10741108 x , y , u , v = delete_masked_points (self .x .ravel (), self .y .ravel (),
10751109 self .u , self .v )
10761110 xy = np .hstack ((x [:, np .newaxis ], y [:, np .newaxis ]))
1077- collections .PolyCollection .set_offsets (self , xy )
1078- set_offsets .__doc__ = collections .PolyCollection .set_offsets .__doc__
1111+ mcollections .PolyCollection .set_offsets (self , xy )
1112+ set_offsets .__doc__ = mcollections .PolyCollection .set_offsets .__doc__
10791113
10801114 barbs_doc = _barbs_doc
0 commit comments