[Matplotlib-users] contourf with rgba colours

I'm switching this to the devel list.

Please try
https://github.com/efiring/matplotlib/tree/colormap_alpha
which has changes similar to yours so that alpha is fully changeable in colormaps.

I think this is going to be OK as far as the colormap end of things is concerned, but it turns up a new problem related to alpha in images, and reminds us of an old problem with alpha in agg, at least. The problems are illustrated in the attached modification of the custom_cmap.py example. I added a fourth panel for testing alpha. Look at the comments on the code for that panel, and try switching between pcolormesh and imshow. Pcolormesh basically works as expected, except for the prominent artifacts on patch boundaries (visible also in the colorbar for that panel). These boundary artifacts are the old problem. The new problem is that imshow with alpha in the colormap is completely wonky with a white background, but looks more normal with a black background--which is not so good if what you really want is a white background showing through the transparency.

Eric

custom_cmap.py (5.89 KB)

···

On 12/30/2011 01:57 PM, Paul Ivanov wrote:

Eric Firing, on 2011-12-27 15:31, wrote:

It looks like this is something I can fix by modifying ListedColormap.
It is discarding the alpha values, and I don't think there is any reason
it needs to do so.

One of my first attempts at a contribution to matplotlib three
years ago was related to this. It was in reply to a similar
question on list, and I wrote a patch, but never saw it through
to inclusion because it wasn't something I needed.

http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg09216.html

I think it's a helpful starting point, as I include a discussion
on the limitation of mpl colormaps there.

This is great! I had hacked together a custom colormap class and overrode its call method to get a similar effect. This solution is much more elegant and general.

As for the imshow issue, it seems to be an issue with the “nearest” interpolation method. The example copied below shows the result for three different interpolation methods. The weird behavior only occurs when interpolation is set to ‘nearest’ (I checked all other interpolation methods, not just the 3 below). What’s really strange is that interpolation='none' gives the expected result, but in theory, ‘none’ maps to the same interpolation function as ‘nearest’. A quick scan of matplotlib.image suggests that ‘none’ and ‘nearest’ share the same code path, but I’m obviously missing something.

-Tony

···

On Mon, Jan 2, 2012 at 3:33 PM, Eric Firing <efiring@…229…> wrote:

On 12/30/2011 01:57 PM, Paul Ivanov wrote:

Eric Firing, on 2011-12-27 15:31, wrote:

It looks like this is something I can fix by modifying ListedColormap.

It is discarding the alpha values, and I don’t think there is any reason

it needs to do so.

One of my first attempts at a contribution to matplotlib three

years ago was related to this. It was in reply to a similar

question on list, and I wrote a patch, but never saw it through

to inclusion because it wasn’t something I needed.

http://www.mail-archive.com/matplotlib-users@…1041…sourceforge.net/msg09216.html

I think it’s a helpful starting point, as I include a discussion

on the limitation of mpl colormaps there.

I’m switching this to the devel list.

Please try

https://github.com/efiring/matplotlib/tree/colormap_alpha

which has changes similar to yours so that alpha is fully changeable in colormaps.

I think this is going to be OK as far as the colormap end of things is concerned, but it turns up a new problem related to alpha in images, and reminds us of an old problem with alpha in agg, at least. The problems are illustrated in the attached modification of the custom_cmap.py example. I added a fourth panel for testing alpha. Look at the comments on the code for that panel, and try switching between pcolormesh and imshow. Pcolormesh basically works as expected, except for the prominent artifacts on patch boundaries (visible also in the colorbar for that panel). These boundary artifacts are the old problem. The new problem is that imshow with alpha in the colormap is completely wonky with a white background, but looks more normal with a black background–which is not so good if what you really want is a white background showing through the transparency.

Eric

#~~~~
import matplotlib.pyplot as plt

cdict = {‘red’: ((0.0, 0.0, 0.0),
(0.5, 0.8, 1.0),
(1.0, 0.4, 1.0)),

    'green': ((0.0, 0.0, 0.0),

              (0.5, 0.9, 0.9),
              (1.0, 0.0, 0.0)),

    'blue':  ((0.0, 0.0, 0.4),
              (0.5, 1.0, 0.8),
              (1.0, 0.0, 0.0)),

    'alpha': ((0.0, 1.0, 1.0),

              (0.5, 0.3, 0.3),
              (1.0, 1.0, 1.0))}

plt.register_cmap(name=‘BlueRedAlpha’, data=cdict)

if name == ‘main’:
import numpy as np

w = 10

y = np.linspace(0, 2*np.pi, w+1)
Z = np.tile(y, (w+1, 1))

plt.rcParams['image.cmap'] = 'BlueRedAlpha'

f, axes = plt.subplots(ncols=3)
interp_method = ['none', 'bilinear', 'nearest']

for interp, ax in zip(interp_method, axes):
    # Draw a line with low zorder so it will be behind the image.
    ax.plot([0, w], [0, w], color='c', lw=20, zorder=-1)
    ax.imshow(Z, interpolation=interp)

    ax.set_title(interp)

plt.show()

#~~~~

        Eric Firing, on 2011-12-27 15:31, wrote:

            It looks like this is something I can fix by modifying
            ListedColormap.
            It is discarding the alpha values, and I don't think there
            is any reason
            it needs to do so.

        One of my first attempts at a contribution to matplotlib three
        years ago was related to this. It was in reply to a similar
        question on list, and I wrote a patch, but never saw it through
        to inclusion because it wasn't something I needed.

        http://www.mail-archive.com/__matplotlib-users@...1042.../msg09216.html
        <http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg09216.html>

        I think it's a helpful starting point, as I include a discussion
        on the limitation of mpl colormaps there.

    I'm switching this to the devel list.

    Please try
    https://github.com/efiring/__matplotlib/tree/colormap_alpha
    <https://github.com/efiring/matplotlib/tree/colormap_alpha>
    which has changes similar to yours so that alpha is fully changeable
    in colormaps.

    I think this is going to be OK as far as the colormap end of things
    is concerned, but it turns up a new problem related to alpha in
    images, and reminds us of an old problem with alpha in agg, at
    least. The problems are illustrated in the attached modification of
    the custom_cmap.py example. I added a fourth panel for testing
    alpha. Look at the comments on the code for that panel, and try
    switching between pcolormesh and imshow. Pcolormesh basically works
    as expected, except for the prominent artifacts on patch boundaries
    (visible also in the colorbar for that panel). These boundary
    artifacts are the old problem. The new problem is that imshow with
    alpha in the colormap is completely wonky with a white background,
    but looks more normal with a black background--which is not so good
    if what you really want is a white background showing through the
    transparency.

    Eric

This is great! I had hacked together a custom colormap class and
overrode its __call__ method to get a similar effect. This solution is
much more elegant and general.

As for the imshow issue, it seems to be an issue with the "nearest"
interpolation method. The example copied below shows the result for
three different interpolation methods. The weird behavior only occurs
when interpolation is set to 'nearest' (I checked all other
interpolation methods, not just the 3 below). What's really strange is
that `interpolation='none'` gives the expected result, but in theory,
'none' maps to the same interpolation function as 'nearest'. A quick
scan of matplotlib.image suggests that 'none' and 'nearest' share the
same code path, but I'm obviously missing something.

It looks to me like 'none' is going through _draw_unsampled_image instead of the path that all the other interpolations, including 'nearest' go through. I think that JJ put in this unsampled functionality about two years ago. I've never dug into the guts of image operations and rendering, so I don't even understand what sort of "sampling" is referred to here.

Eric

···

On 01/02/2012 05:51 PM, Tony Yu wrote:

On Mon, Jan 2, 2012 at 3:33 PM, Eric Firing <efiring@…229… > <mailto:efiring@…229…>> wrote:
    On 12/30/2011 01:57 PM, Paul Ivanov wrote:

-Tony

#~~~~
import matplotlib.pyplot as plt

cdict = {'red': ((0.0, 0.0, 0.0),
                   (0.5, 0.8, 1.0),
                   (1.0, 0.4, 1.0)),

'green': ((0.0, 0.0, 0.0),
                   (0.5, 0.9, 0.9),
                   (1.0, 0.0, 0.0)),

'blue': ((0.0, 0.0, 0.4),
                   (0.5, 1.0, 0.8),
                   (1.0, 0.0, 0.0)),

'alpha': ((0.0, 1.0, 1.0),
                   (0.5, 0.3, 0.3),
                   (1.0, 1.0, 1.0))}

plt.register_cmap(name='BlueRedAlpha', data=cdict)

if __name__ == '__main__':
     import numpy as np

     w = 10
     y = np.linspace(0, 2*np.pi, w+1)
     Z = np.tile(y, (w+1, 1))

     plt.rcParams['image.cmap'] = 'BlueRedAlpha'

     f, axes = plt.subplots(ncols=3)
     interp_method = ['none', 'bilinear', 'nearest']
     for interp, ax in zip(interp_method, axes):
         # Draw a line with low zorder so it will be behind the image.
         ax.plot([0, w], [0, w], color='c', lw=20, zorder=-1)
         ax.imshow(Z, interpolation=interp)
         ax.set_title(interp)

     plt.show()
#~~~~

Well, that’s embarrassing: Apparently I searched for ‘none’ with single quotes, but not double quotes.

Unfortunately, I can’t figure out the issue, but while debugging, I noticed that constant alpha values have the same issue. For example, if you replace the alpha spec in the custom colormap with:

 'alpha': ((0.0, 0.7, 0.7),
              (1.0, 0.7, 0.7))}

then you see the same issue. If, however, you set alpha to 1 in the colormap, but set alpha=1 in imshow, then everything works as expected.

It almost seems like it maybe an overflow issue. As you gradually decrease the alpha value (in the colormap, not in imshow), the whiter colors start to get weird, then successively darker colors get weird—you can check this with the script copied below.

In any case, I think the problem is in C-code, which I’m not really equipped to debug. Hopefully, someone else can track this down.

-Tony

import numpy as np
import matplotlib.pyplot as plt

from matplotlib.colors import LinearSegmentedColormap

cdict = {‘red’: ((0.0, 0.0, 0.0),
(0.5, 0.8, 1.0),
(1.0, 0.4, 1.0)),

    'green': ((0.0, 0.0, 0.0),

              (0.5, 0.9, 0.9),
              (1.0, 0.0, 0.0)),

    'blue':  ((0.0, 0.0, 0.4),
              (0.5, 1.0, 0.8),
              (1.0, 0.0, 0.0))}

w = 10
y = np.linspace(0, 2*np.pi, w+1)

Z = np.tile(y, (w+1, 1))

alpha_values = (1, 0.9, 0.7, 0.5)

f, axes = plt.subplots(ncols=len(alpha_values))
for i, (ax, alpha) in enumerate(zip(axes, alpha_values)):
cdict = cdict.copy()
cdict[‘alpha’] = [(0.0, alpha, alpha), (1.0, alpha, alpha)]

cmap = LinearSegmentedColormap('BlueRedAlpha%i' % i, cdict)
im = ax.imshow(Z, interpolation='nearest', cmap=cmap)
ax.set_title('alpha = %g' % alpha)

plt.show()

···

On Tue, Jan 3, 2012 at 1:10 AM, Eric Firing <efiring@…229…> wrote:

On 01/02/2012 05:51 PM, Tony Yu wrote:

On Mon, Jan 2, 2012 at 3:33 PM, Eric Firing <efiring@…229… > > mailto:efiring@...55.....229...> wrote:

On 12/30/2011 01:57 PM, Paul Ivanov wrote:



    Eric Firing, on 2011-12-27 15:31,  wrote:



        It looks like this is something I can fix by modifying

        ListedColormap.

        It is discarding the alpha values, and I don't think there

        is any reason

        it needs to do so.





    One of my first attempts at a contribution to matplotlib three

    years ago was related to this. It was in reply to a similar

    question on list, and I wrote a patch, but never saw it through

    to inclusion because it wasn't something I needed.

http://www.mail-archive.com/__matplotlib-users@…1043…sourceforge.net/msg09216.html

    <[http://www.mail-archive.com/matplotlib-users@...1041...sourceforge.net/msg09216.html](http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg09216.html)>







    I think it's a helpful starting point, as I include a discussion

    on the limitation of mpl colormaps there.





I'm switching this to the devel list.



Please try

https://github.com/efiring/__matplotlib/tree/colormap_alpha

<[https://github.com/efiring/matplotlib/tree/colormap_alpha](https://github.com/efiring/matplotlib/tree/colormap_alpha)>

which has changes similar to yours so that alpha is fully changeable

in colormaps.



I think this is going to be OK as far as the colormap end of things

is concerned, but it turns up a new problem related to alpha in

images, and reminds us of an old problem with alpha in agg, at

least.  The problems are illustrated in the attached modification of

the custom_cmap.py example.  I added a fourth panel for testing

alpha.  Look at the comments on the code for that panel, and try

switching between pcolormesh and imshow.  Pcolormesh basically works

as expected, except for the prominent artifacts on patch boundaries

(visible also in the colorbar for that panel).  These boundary

artifacts are the old problem. The new problem is that imshow with

alpha in the colormap is completely wonky with a white background,

but looks more normal with a black background--which is not so good

if what you really want is a white background showing through the

transparency.



Eric

This is great! I had hacked together a custom colormap class and

overrode its call method to get a similar effect. This solution is

much more elegant and general.

As for the imshow issue, it seems to be an issue with the “nearest”

interpolation method. The example copied below shows the result for

three different interpolation methods. The weird behavior only occurs

when interpolation is set to ‘nearest’ (I checked all other

interpolation methods, not just the 3 below). What’s really strange is

that interpolation='none' gives the expected result, but in theory,

‘none’ maps to the same interpolation function as ‘nearest’. A quick

scan of matplotlib.image suggests that ‘none’ and ‘nearest’ share the

same code path, but I’m obviously missing something.

It looks to me like ‘none’ is going through _draw_unsampled_image instead of the path that all the other interpolations, including ‘nearest’ go through. I think that JJ put in this unsampled functionality about two years ago. I’ve never dug into the guts of image operations and rendering, so I don’t even understand what sort of “sampling” is referred to here.

Eric

I think I’ve discovered the root of this problem.

A change was made during the 1.1.x cycle to tell Agg that we're

giving it premultiplied alpha in the image data (see commit
1dac36d829). This made displaying images loaded from files that had
an alpha channel work correctly and made it consistent with the PDF
and SVG backends. Unfortunately, that seems to have broken things
for colormapped images where the colormapping does not generate
premultiplied alpha. (That weird coloring thing was due to Agg
“clipping” the r, g, b values to be <= a, which it does when it’s
expecting pre-multiplied alpha).

I believe the fix is to premultiply the image right after

colormapping it. I’ve submitted a pull request against efiring’s
alpha_colormap branch that does this. This is just a quick
proof-of-concept fix – no guarantees that it’s complete and doesn’t
have any unintended consequences.

Note that we can't just do the premultiplication in the color

mapping class itself, since other things in the Agg backend (such as
line drawing) do not expect premultiplied alpha – premultiplication
should only be applied to images. The side benefit is that this
change also makes the output of the PDF and SVG backends agree with
the Agg backend.

Mike
···

http://p.sf.net/sfu/Citrix-VDIinaboxMatplotlib-devel@lists.sourceforge.nethttps://lists.sourceforge.net/lists/listinfo/matplotlib-devel