@@ -289,18 +289,40 @@ def to_rgba_array(c, alpha=None):
289
289
"""
290
290
Convert *c* to a (n, 4) array of RGBA colors.
291
291
292
- If *alpha* is not ``None``, it forces the alpha value. If *c* is
293
- ``"none"`` (case-insensitive) or an empty list, an empty array is returned.
294
- If *c* is a masked array, an ndarray is returned with a (0, 0, 0, 0)
295
- row for each masked value or row in *c*.
292
+ Parameters
293
+ ----------
294
+ c : Matplotlib color or array of colors
295
+ If *c* is a masked array, an ndarray is returned with a (0, 0, 0, 0)
296
+ row for each masked value or row in *c*.
297
+
298
+ alpha : float or sequence of floats, optional
299
+ If *alpha* is not ``None``, it forces the alpha value, except if *c* is
300
+ ``"none"`` (case-insensitive), which always maps to ``(0, 0, 0, 0)``.
301
+ If *alpha* is a sequence and *c* is a single color, *c* will be
302
+ repeated to match the length of *alpha*.
303
+
304
+ Returns
305
+ -------
306
+ array
307
+ (n, 4) array of RGBA colors.
308
+
296
309
"""
297
310
# Special-case inputs that are already arrays, for performance. (If the
298
311
# array has the wrong kind or shape, raise the error during one-at-a-time
299
312
# conversion.)
313
+ if np .iterable (alpha ):
314
+ alpha = np .asarray (alpha ).ravel ()
300
315
if (isinstance (c , np .ndarray ) and c .dtype .kind in "if"
301
316
and c .ndim == 2 and c .shape [1 ] in [3 , 4 ]):
302
317
mask = c .mask .any (axis = 1 ) if np .ma .is_masked (c ) else None
303
318
c = np .ma .getdata (c )
319
+ if np .iterable (alpha ):
320
+ if c .shape [0 ] == 1 and alpha .shape [0 ] > 1 :
321
+ c = np .tile (c , (alpha .shape [0 ], 1 ))
322
+ elif c .shape [0 ] != alpha .shape [0 ]:
323
+ raise ValueError ("The number of colors must match the number"
324
+ " of alpha values if there are more than one"
325
+ " of each." )
304
326
if c .shape [1 ] == 3 :
305
327
result = np .column_stack ([c , np .zeros (len (c ))])
306
328
result [:, - 1 ] = alpha if alpha is not None else 1.
@@ -320,7 +342,10 @@ def to_rgba_array(c, alpha=None):
320
342
if cbook ._str_lower_equal (c , "none" ):
321
343
return np .zeros ((0 , 4 ), float )
322
344
try :
323
- return np .array ([to_rgba (c , alpha )], float )
345
+ if np .iterable (alpha ):
346
+ return np .array ([to_rgba (c , a ) for a in alpha ], float )
347
+ else :
348
+ return np .array ([to_rgba (c , alpha )], float )
324
349
except (ValueError , TypeError ):
325
350
pass
326
351
@@ -332,7 +357,10 @@ def to_rgba_array(c, alpha=None):
332
357
if len (c ) == 0 :
333
358
return np .zeros ((0 , 4 ), float )
334
359
else :
335
- return np .array ([to_rgba (cc , alpha ) for cc in c ])
360
+ if np .iterable (alpha ):
361
+ return np .array ([to_rgba (cc , aa ) for cc , aa in zip (c , alpha )])
362
+ else :
363
+ return np .array ([to_rgba (cc , alpha ) for cc in c ])
336
364
337
365
338
366
def to_rgb (c ):
@@ -539,8 +567,9 @@ def __call__(self, X, alpha=None, bytes=False):
539
567
return the RGBA values ``X*100`` percent along the Colormap line.
540
568
For integers, X should be in the interval ``[0, Colormap.N)`` to
541
569
return RGBA values *indexed* from the Colormap with index ``X``.
542
- alpha : float, None
543
- Alpha must be a scalar between 0 and 1, or None.
570
+ alpha : float, array-like, None
571
+ Alpha must be a scalar between 0 and 1, a sequence of such
572
+ floats with shape matching X, or None.
544
573
bytes : bool
545
574
If False (default), the returned RGBA values will be floats in the
546
575
interval ``[0, 1]`` otherwise they will be uint8s in the interval
@@ -580,23 +609,29 @@ def __call__(self, X, alpha=None, bytes=False):
580
609
else :
581
610
lut = self ._lut .copy () # Don't let alpha modify original _lut.
582
611
612
+ rgba = np .empty (shape = xa .shape + (4 ,), dtype = lut .dtype )
613
+ lut .take (xa , axis = 0 , mode = 'clip' , out = rgba )
614
+
583
615
if alpha is not None :
616
+ if np .iterable (alpha ):
617
+ alpha = np .asarray (alpha )
618
+ if alpha .shape != xa .shape :
619
+ raise ValueError ("alpha is array-like but its shape"
620
+ " %s doesn't match that of X %s" %
621
+ (alpha .shape , xa .shape ))
584
622
alpha = np .clip (alpha , 0 , 1 )
585
623
if bytes :
586
- alpha = int (alpha * 255 )
587
- if (lut [- 1 ] == 0 ).all ():
588
- lut [:- 1 , - 1 ] = alpha
589
- # All zeros is taken as a flag for the default bad
590
- # color, which is no color--fully transparent. We
591
- # don't want to override this.
592
- else :
593
- lut [:, - 1 ] = alpha
594
- # If the bad value is set to have a color, then we
595
- # override its alpha just as for any other value.
624
+ alpha = (alpha * 255 ).astype (np .uint8 )
625
+ rgba [..., - 1 ] = alpha
626
+
627
+ # If the "bad" color is all zeros, then ignore alpha input.
628
+ if (lut [- 1 ] == 0 ).all () and np .any (mask_bad ):
629
+ if np .iterable (mask_bad ) and mask_bad .shape == xa .shape :
630
+ rgba [mask_bad ] = (0 , 0 , 0 , 0 )
631
+ else :
632
+ rgba [..., :] = (0 , 0 , 0 , 0 )
596
633
597
- rgba = lut [xa ]
598
634
if not np .iterable (X ):
599
- # Return a tuple if the input was a scalar
600
635
rgba = tuple (rgba )
601
636
return rgba
602
637
0 commit comments