Is this a bug in LineCollection's handling of alpha values?

Hi all,

Hopefully the code below is illustrative and commented enough to
clarify my question (also attached if you prefer to download it than
to copy/paste).

Cheers,

f

"""LineCollection ignores alpha value?

The second figure below works, but it sets alpha globally for the whole
collection. If LineCollection accepts rgbA tuples, why does it ignore the
alpha channel? Is it possible somehow to have alpha for each line (without
having to make a single-line collection each time?
"""

from matplotlib import pyplot as plt
from matplotlib.collections import LineCollection

# Make two lines
line0 = [(0,0),(1,1)]
line1 = [(1,0),(0,1)]
lines = [line0,line1]

# Make colors for each. Note alpha is 0.2, so they should be fairly faint, the
# red one is meant to be darker than the blue one
alpha = 0.2
colors = [(0,0,1,alpha), # blue line
          (1,0,0,2*alpha)] # red line

# Make a figure with these
f = plt.figure()
ax = f.add_subplot(111)
lc = LineCollection(lines,10,colors)
ax.add_collection(lc)

# Another figure, where we set the alpha globally for the line collection
f = plt.figure()
ax = f.add_subplot(111)
lc = LineCollection(lines,10,colors)
lc.set_alpha(alpha)
ax.add_collection(lc)

plt.show()

ex_linecoll.py (1.02 KB)

Hey Fernando -- thanks for the report and test case.

I committed a change to svn which fixes this -- I'd like one of the
color gurus (Eric?) to take a look at this because the color handling
code is fairly complex as it handles a lot of different cases. The
problem here was that the ColorConverter.to_rgba_array was applying
the alpha even though the input array was rgba already. I special
case this and do not convert when the input is already an Nx4 array.
Are there any cases I am missing? See the inline comment below:

    def to_rgba_array(self, c, alpha=None):
        """
        Returns a numpy array of *RGBA* tuples.

        Accepts a single mpl color spec or a sequence of specs.

        Special case to handle "no color": if *c* is "none" (case-insensitive),
        then an empty array will be returned. Same for an empty list.
        """
        try:
            if c.lower() == 'none':
                return np.zeros((0,4), dtype=np.float_)
        except AttributeError:
            pass
        if len(c) == 0:
            return np.zeros((0,4), dtype=np.float_)
        try:
            result = np.array([self.to_rgba(c, alpha)], dtype=np.float_)
        except ValueError:
            if isinstance(c, np.ndarray):
                if c.ndim != 2 and c.dtype.kind not in 'SU':
                    raise ValueError("Color array must be two-dimensional")
                if len(c.shape)==2 and c.shape[-1]==4:
                    # looks like rgba already, nothing to be done; do
                    # we want to apply alpha here if
                    # (c[:,3]==1).all() ?
                    return c
            result = np.zeros((len(c), 4))
            for i, cc in enumerate(c):
                result[i] = self.to_rgba(cc, alpha) # change in place
        return np.asarray(result, np.float_)

JDH

···

On Fri, Jun 5, 2009 at 9:56 PM, Fernando Perez<fperez.net@...149...> wrote:

Hopefully the code below is illustrative and commented enough to
clarify my question (also attached if you prefer to download it than
to copy/paste).

Hey John,

Hey Fernando -- thanks for the report and test case.

I committed a change to svn which fixes this

Awesome, many thanks! This is really great, the Berkeley neuroscience
team continues to be impressed by how fast bugs get fixed in the open
source python projects (we had a similar one for numpy a few days
ago).

The comment I just got was: "Wow, people like fixing bugs?"

:slight_smile:

Cheers,

f

···

On Sat, Jun 6, 2009 at 4:40 AM, John Hunter<jdh2358@...149...> wrote: