14
14
the Quiver code.
15
15
"""
16
16
17
-
18
17
from __future__ import print_function , division
18
+ import weakref
19
+
19
20
import numpy as np
20
21
from numpy import ma
21
- import matplotlib .collections as collections
22
+ import matplotlib .collections as mcollections
22
23
import matplotlib .transforms as transforms
23
24
import matplotlib .text as mtext
24
25
import matplotlib .artist as martist
219
220
220
221
class QuiverKey (martist .Artist ):
221
222
""" 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' }
225
226
226
227
def __init__ (self , Q , X , Y , U , label , ** kw ):
227
228
martist .Artist .__init__ (self )
@@ -235,13 +236,19 @@ def __init__(self, Q, X, Y, U, label, **kw):
235
236
self ._labelsep_inches = kw .pop ('labelsep' , 0.1 )
236
237
self .labelsep = (self ._labelsep_inches * Q .ax .figure .dpi )
237
238
239
+ # try to prevent closure over the real self
240
+ weak_self = weakref .ref (self )
241
+
238
242
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.
243
249
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 )
245
252
246
253
self .labelpos = kw .pop ('labelpos' , 'N' )
247
254
self .labelcolor = kw .pop ('labelcolor' , None )
@@ -254,11 +261,21 @@ def on_dpi_change(fig):
254
261
horizontalalignment = self .halign [self .labelpos ],
255
262
verticalalignment = self .valign [self .labelpos ],
256
263
fontproperties = font_manager .FontProperties (** _fp ))
264
+
257
265
if self .labelcolor is not None :
258
266
self .text .set_color (self .labelcolor )
259
267
self ._initialized = False
260
268
self .zorder = Q .zorder + 0.1
261
269
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
+
262
279
__init__ .__doc__ = _quiverkey_doc
263
280
264
281
def _init (self ):
@@ -275,7 +292,7 @@ def _init(self):
275
292
self .Q .pivot = _pivot
276
293
kw = self .Q .polykw
277
294
kw .update (self .kw )
278
- self .vector = collections .PolyCollection (
295
+ self .vector = mcollections .PolyCollection (
279
296
self .verts ,
280
297
offsets = [(self .X , self .Y )],
281
298
transOffset = self .get_transform (),
@@ -364,7 +381,7 @@ def _parse_args(*args):
364
381
return X , Y , U , V , C
365
382
366
383
367
- class Quiver (collections .PolyCollection ):
384
+ class Quiver (mcollections .PolyCollection ):
368
385
"""
369
386
Specialized PolyCollection for arrows.
370
387
@@ -411,7 +428,7 @@ def __init__(self, ax, *args, **kw):
411
428
self .transform = kw .pop ('transform' , ax .transData )
412
429
kw .setdefault ('facecolors' , self .color )
413
430
kw .setdefault ('linewidths' , (0 ,))
414
- collections .PolyCollection .__init__ (self , [], offsets = self .XY ,
431
+ mcollections .PolyCollection .__init__ (self , [], offsets = self .XY ,
415
432
transOffset = self .transform ,
416
433
closed = False ,
417
434
** kw )
@@ -422,14 +439,30 @@ def __init__(self, ax, *args, **kw):
422
439
self .keyvec = None
423
440
self .keytext = None
424
441
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 )
431
444
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 )
433
466
434
467
def _init (self ):
435
468
"""
@@ -456,7 +489,7 @@ def draw(self, renderer):
456
489
verts = self ._make_verts (self .U , self .V )
457
490
self .set_verts (verts , closed = False )
458
491
self ._new_UV = False
459
- collections .PolyCollection .draw (self , renderer )
492
+ mcollections .PolyCollection .draw (self , renderer )
460
493
461
494
def set_UVC (self , U , V , C = None ):
462
495
U = ma .masked_invalid (U , copy = False ).ravel ()
@@ -789,7 +822,7 @@ def _h_arrows(self, length):
789
822
docstring .interpd .update (barbs_doc = _barbs_doc )
790
823
791
824
792
- class Barbs (collections .PolyCollection ):
825
+ class Barbs (mcollections .PolyCollection ):
793
826
'''
794
827
Specialized PolyCollection for barbs.
795
828
@@ -850,8 +883,9 @@ def __init__(self, ax, *args, **kw):
850
883
851
884
#Make a collection
852
885
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 )
855
889
self .set_transform (transforms .IdentityTransform ())
856
890
857
891
self .set_UVC (u , v , c )
@@ -1074,7 +1108,7 @@ def set_offsets(self, xy):
1074
1108
x , y , u , v = delete_masked_points (self .x .ravel (), self .y .ravel (),
1075
1109
self .u , self .v )
1076
1110
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__
1079
1113
1080
1114
barbs_doc = _barbs_doc
0 commit comments