14
14
the Quiver code.
15
15
"""
16
16
17
-
18
17
from __future__ import (absolute_import , division , print_function ,
19
18
unicode_literals )
20
19
21
20
import six
21
+ import weakref
22
22
23
23
import numpy as np
24
24
from numpy import ma
25
- import matplotlib .collections as collections
25
+ import matplotlib .collections as mcollections
26
26
import matplotlib .transforms as transforms
27
27
import matplotlib .text as mtext
28
28
import matplotlib .artist as martist
223
223
224
224
class QuiverKey (martist .Artist ):
225
225
""" 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' }
229
229
230
230
def __init__ (self , Q , X , Y , U , label , ** kw ):
231
231
martist .Artist .__init__ (self )
@@ -239,13 +239,19 @@ def __init__(self, Q, X, Y, U, label, **kw):
239
239
self ._labelsep_inches = kw .pop ('labelsep' , 0.1 )
240
240
self .labelsep = (self ._labelsep_inches * Q .ax .figure .dpi )
241
241
242
+ # try to prevent closure over the real self
243
+ weak_self = weakref .ref (self )
244
+
242
245
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.
247
252
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 )
249
255
250
256
self .labelpos = kw .pop ('labelpos' , 'N' )
251
257
self .labelcolor = kw .pop ('labelcolor' , None )
@@ -258,11 +264,21 @@ def on_dpi_change(fig):
258
264
horizontalalignment = self .halign [self .labelpos ],
259
265
verticalalignment = self .valign [self .labelpos ],
260
266
fontproperties = font_manager .FontProperties (** _fp ))
267
+
261
268
if self .labelcolor is not None :
262
269
self .text .set_color (self .labelcolor )
263
270
self ._initialized = False
264
271
self .zorder = Q .zorder + 0.1
265
272
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
+
266
282
__init__ .__doc__ = _quiverkey_doc
267
283
268
284
def _init (self ):
@@ -279,7 +295,7 @@ def _init(self):
279
295
self .Q .pivot = _pivot
280
296
kw = self .Q .polykw
281
297
kw .update (self .kw )
282
- self .vector = collections .PolyCollection (
298
+ self .vector = mcollections .PolyCollection (
283
299
self .verts ,
284
300
offsets = [(self .X , self .Y )],
285
301
transOffset = self .get_transform (),
@@ -368,7 +384,7 @@ def _parse_args(*args):
368
384
return X , Y , U , V , C
369
385
370
386
371
- class Quiver (collections .PolyCollection ):
387
+ class Quiver (mcollections .PolyCollection ):
372
388
"""
373
389
Specialized PolyCollection for arrows.
374
390
@@ -415,7 +431,7 @@ def __init__(self, ax, *args, **kw):
415
431
self .transform = kw .pop ('transform' , ax .transData )
416
432
kw .setdefault ('facecolors' , self .color )
417
433
kw .setdefault ('linewidths' , (0 ,))
418
- collections .PolyCollection .__init__ (self , [], offsets = self .XY ,
434
+ mcollections .PolyCollection .__init__ (self , [], offsets = self .XY ,
419
435
transOffset = self .transform ,
420
436
closed = False ,
421
437
** kw )
@@ -426,14 +442,30 @@ def __init__(self, ax, *args, **kw):
426
442
self .keyvec = None
427
443
self .keytext = None
428
444
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 )
435
447
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 )
437
469
438
470
def _init (self ):
439
471
"""
@@ -460,7 +492,7 @@ def draw(self, renderer):
460
492
verts = self ._make_verts (self .U , self .V )
461
493
self .set_verts (verts , closed = False )
462
494
self ._new_UV = False
463
- collections .PolyCollection .draw (self , renderer )
495
+ mcollections .PolyCollection .draw (self , renderer )
464
496
465
497
def set_UVC (self , U , V , C = None ):
466
498
U = ma .masked_invalid (U , copy = False ).ravel ()
@@ -793,7 +825,7 @@ def _h_arrows(self, length):
793
825
docstring .interpd .update (barbs_doc = _barbs_doc )
794
826
795
827
796
- class Barbs (collections .PolyCollection ):
828
+ class Barbs (mcollections .PolyCollection ):
797
829
'''
798
830
Specialized PolyCollection for barbs.
799
831
@@ -854,8 +886,9 @@ def __init__(self, ax, *args, **kw):
854
886
855
887
#Make a collection
856
888
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 )
859
892
self .set_transform (transforms .IdentityTransform ())
860
893
861
894
self .set_UVC (u , v , c )
@@ -1078,7 +1111,7 @@ def set_offsets(self, xy):
1078
1111
x , y , u , v = delete_masked_points (self .x .ravel (), self .y .ravel (),
1079
1112
self .u , self .v )
1080
1113
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__
1083
1116
1084
1117
barbs_doc = _barbs_doc
0 commit comments