@@ -253,8 +253,12 @@ def _init(self):
253
253
self ._set_transform ()
254
254
_pivot = self .Q .pivot
255
255
self .Q .pivot = self .pivot [self .labelpos ]
256
+ # Hack: save and restore the Umask
257
+ _mask = self .Q .Umask
258
+ self .Q .Umask = ma .nomask
256
259
self .verts = self .Q ._make_verts (np .array ([self .U ]),
257
260
np .zeros ((1 ,)))
261
+ self .Q .Umask = _mask
258
262
self .Q .pivot = _pivot
259
263
kw = self .Q .polykw
260
264
kw .update (self .kw )
@@ -388,9 +392,9 @@ def _parse_args(self, *args):
388
392
X , Y , U , V , C = [None ]* 5
389
393
args = list (args )
390
394
if len (args ) == 3 or len (args ) == 5 :
391
- C = ma . masked_invalid (args .pop (- 1 ), copy = False )
392
- V = ma . masked_invalid (args .pop (- 1 ), copy = False )
393
- U = ma . masked_invalid (args .pop (- 1 ), copy = False )
395
+ C = np . asanyarray (args .pop (- 1 ))
396
+ V = np . asanyarray (args .pop (- 1 ))
397
+ U = np . asanyarray (args .pop (- 1 ))
394
398
if U .ndim == 1 :
395
399
nr , nc = 1 , U .shape [0 ]
396
400
else :
@@ -430,10 +434,21 @@ def draw(self, renderer):
430
434
collections .PolyCollection .draw (self , renderer )
431
435
432
436
def set_UVC (self , U , V , C = None ):
433
- self .U = U .ravel ()
434
- self .V = V .ravel ()
437
+ U = ma .masked_invalid (U , copy = False ).ravel ()
438
+ V = ma .masked_invalid (V , copy = False ).ravel ()
439
+ mask = ma .mask_or (U .mask , V .mask , copy = False , shrink = True )
440
+ if C is not None :
441
+ C = ma .masked_invalid (C , copy = False ).ravel ()
442
+ mask = ma .mask_or (mask , C .mask , copy = False , shrink = True )
443
+ if mask is ma .nomask :
444
+ C = C .filled ()
445
+ else :
446
+ C = ma .array (C , mask = mask , copy = False )
447
+ self .U = U .filled (1 )
448
+ self .V = V .filled (1 )
449
+ self .Umask = mask
435
450
if C is not None :
436
- self .set_array (C . ravel () )
451
+ self .set_array (C )
437
452
self ._new_UV = True
438
453
439
454
def _set_transform (self ):
@@ -463,32 +478,33 @@ def _set_transform(self):
463
478
464
479
def _angles (self , U , V , eps = 0.001 ):
465
480
xy = self .ax .transData .transform (self .XY )
466
- uv = ma .hstack ((U [:,np .newaxis ], V [:,np .newaxis ])). filled ( 0 )
481
+ uv = np .hstack ((U [:,np .newaxis ], V [:,np .newaxis ]))
467
482
xyp = self .ax .transData .transform (self .XY + eps * uv )
468
483
dxy = xyp - xy
469
- ang = ma .arctan2 (dxy [:,1 ], dxy [:,0 ])
484
+ ang = np .arctan2 (dxy [:,1 ], dxy [:,0 ])
470
485
return ang
471
486
472
487
def _make_verts (self , U , V ):
473
- uv = ma . asarray (U + V * 1j )
474
- a = ma .absolute (uv )
488
+ uv = (U + V * 1j )
489
+ a = np .absolute (uv )
475
490
if self .scale is None :
476
491
sn = max (10 , math .sqrt (self .N ))
477
- scale = 1.8 * a .mean () * sn / self .span # crude auto-scaling
492
+ scale = 1.8 * a [ ~ self . Umask ] .mean () * sn / self .span # crude auto-scaling
478
493
self .scale = scale
479
494
length = a / (self .scale * self .width )
480
495
X , Y = self ._h_arrows (length )
481
496
if self .angles == 'xy' :
482
- theta = self ._angles (U , V ). filled ( 0 )
497
+ theta = self ._angles (U , V )
483
498
elif self .angles == 'uv' :
484
- theta = np .angle (uv . filled ( 0 ) )
499
+ theta = np .angle (uv )
485
500
else :
486
501
theta = ma .masked_invalid (self .angles , copy = False ).filled (0 )
487
502
theta *= (np .pi / 180.0 )
488
503
theta .shape = (theta .shape [0 ], 1 ) # for broadcasting
489
504
xy = (X + Y * 1j ) * np .exp (1j * theta )* self .width
490
505
xy = xy [:,:,np .newaxis ]
491
- XY = ma .concatenate ((xy .real , xy .imag ), axis = 2 )
506
+ XY = np .concatenate ((xy .real , xy .imag ), axis = 2 )
507
+
492
508
return XY
493
509
494
510
@@ -502,8 +518,8 @@ def _h_arrows(self, length):
502
518
length = length .reshape (N , 1 )
503
519
# This number is chosen based on when pixel values overflow in Agg
504
520
# causing rendering errors
505
- length = np .minimum (length , 2 ** 16 )
506
-
521
+ # length = np.minimum(length, 2 ** 16)
522
+ np . clip ( length , 0 , 2 ** 16 , out = length )
507
523
# x, y: normal horizontal arrow
508
524
x = np .array ([0 , - self .headaxislength ,
509
525
- self .headlength , 0 ], np .float64 )
@@ -514,21 +530,20 @@ def _h_arrows(self, length):
514
530
x0 = np .array ([0 , minsh - self .headaxislength ,
515
531
minsh - self .headlength , minsh ], np .float64 )
516
532
y0 = 0.5 * np .array ([1 , 1 , self .headwidth , 0 ], np .float64 )
517
- ii = [0 ,1 ,2 ,3 ,2 ,1 ,0 ]
533
+ ii = [0 ,1 ,2 ,3 ,2 ,1 ,0 , 0 ]
518
534
X = x .take (ii , 1 )
519
535
Y = y .take (ii , 1 )
520
- Y [:, 3 :] *= - 1
536
+ Y [:, 3 :- 1 ] *= - 1
521
537
X0 = x0 .take (ii )
522
538
Y0 = y0 .take (ii )
523
- Y0 [3 :] *= - 1
539
+ Y0 [3 :- 1 ] *= - 1
524
540
shrink = length / minsh
525
541
X0 = shrink * X0 [np .newaxis ,:]
526
542
Y0 = shrink * Y0 [np .newaxis ,:]
527
- short = np .repeat (length < minsh , 7 , axis = 1 )
528
- #print 'short', length < minsh
543
+ short = np .repeat (length < minsh , 8 , axis = 1 )
529
544
# Now select X0, Y0 if short, otherwise X, Y
530
- X = ma . where ( short , X0 , X )
531
- Y = ma . where ( short , Y0 , Y )
545
+ np . putmask ( X , short , X0 )
546
+ np . putmask ( Y , short , Y0 )
532
547
if self .pivot [:3 ] == 'mid' :
533
548
X -= 0.5 * X [:,3 , np .newaxis ]
534
549
elif self .pivot [:3 ] == 'tip' :
@@ -538,14 +553,18 @@ def _h_arrows(self, length):
538
553
tooshort = length < self .minlength
539
554
if tooshort .any ():
540
555
# Use a heptagonal dot:
541
- th = np .arange (0 ,7 ,1 , np .float64 ) * (np .pi / 3.0 )
556
+ th = np .arange (0 ,8 ,1 , np .float64 ) * (np .pi / 3.0 )
542
557
x1 = np .cos (th ) * self .minlength * 0.5
543
558
y1 = np .sin (th ) * self .minlength * 0.5
544
559
X1 = np .repeat (x1 [np .newaxis , :], N , axis = 0 )
545
560
Y1 = np .repeat (y1 [np .newaxis , :], N , axis = 0 )
546
- tooshort = ma .repeat (tooshort , 7 , 1 )
547
- X = ma .where (tooshort , X1 , X )
548
- Y = ma .where (tooshort , Y1 , Y )
561
+ tooshort = np .repeat (tooshort , 8 , 1 )
562
+ np .putmask (X , tooshort , X1 )
563
+ np .putmask (Y , tooshort , Y1 )
564
+ if self .Umask is not ma .nomask :
565
+ mask = np .repeat (self .Umask [:,np .newaxis ], 8 , 1 )
566
+ X = ma .array (X , mask = mask , copy = False )
567
+ Y = ma .array (Y , mask = mask , copy = False )
549
568
return X , Y
550
569
551
570
quiver_doc = _quiver_doc
0 commit comments