contourf looking ugly with transparent colors

Hi,

Does somebody know how to produce a good-looking filled contour plot
with semi-transparent colors? If contourf() is passed a colormap with
semi-transparent colors, it produces small gaps between the filled areas:
http://i.stack.imgur.com/eEQXI.png

According to the docs, this is not a bug ("contourf() [...] does not
draw the polygon edges"). To draw the edges, it is suggested to "add
line contours with calls to contour()". But that doesn't look good
either as the edges become too opaque:
http://i.stack.imgur.com/s17F9.png
You can play with the linewidth argument of contour(), but that doesn't
help much. Any ideas?

The code that reproduces the problem is attached below (I use the
object-oriented API, but the result is the same with pyplot).

BTW, pcolormesh() suffers from a similar problem:
http://i.stack.imgur.com/Gbwcb.png

Both problems do not seem to occur with the SVG backend.

I asked the same question already on stackoverflow. Feel free to respond
there:
http://stackoverflow.com/questions/33547926/matplotlib-filled-contour-plot-with-transparent-colors

Thanks,
Remo

···

---------
import matplotlib
import numpy as np
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg

# generate some data
shape = (100, 100)
x_rng = np.linspace(-1, 1, shape[1])
y_rng = np.linspace(-1, 1, shape[0])
x, y = np.meshgrid(x_rng, y_rng)
z = np.sqrt(x**2 + y**2)

# create figure
width_inch, height_inch = 5, 5 # results in 500x500px with dpi=100
fig = Figure()
fig.set_size_inches((width_inch, height_inch))
FigureCanvasAgg(fig)
ax = fig.add_axes([0., 0., 1., 1.])
ax.set_axis_off()

# define some colors with alpha < 1
alpha = 0.9
colors = [
    (0.1, 0.1, 0.5, alpha), # dark blue
    (0.0, 0.7, 0.3, alpha), # green
    (0.9, 0.2, 0.7, alpha), # pink
    (0.0, 0.0, 0.0, alpha), # black
    (0.1, 0.7, 0.7, alpha), # light blue
]
cmap = matplotlib.colors.ListedColormap(colors)
levels = np.array(np.linspace(0, z.max(), len(colors)))
norm = matplotlib.colors.BoundaryNorm(levels, ncolors=cmap.N)

# contourf plot produces small gaps between filled areas
cnt = ax.contourf(x, y, z, levels, cmap=cmap, norm=norm,
                  antialiased=True, linecolor='none')

# this fills the gaps, but it makes them too opaque
# ax.contour(x, y, z, levels, cmap=cmap, norm=norm,
# antialiased=True)

# the same is true for this trick:
# for c in cnt.collections:
# c.set_edgecolor("face")

filename = "/tmp/contourf.png"
fig.savefig(filename, dpi=100, transparent=True, format="png")
print("Saved plot to {}.".format(filename))

The issue you are seeing is slightly different from the one the docs
mention.
I wrote the docs suggesting the work around and this is mainly relevant for
vector backends (PDF and so on) The problem with PDF viewers is that many
of them create visible gaps when two polygons are rendered next to each
other with zero overlap. This is a viewer specific thing but lots of
viewers suffers from this.
This effect is much more visible that the one you see. I think the one you
see is due to the way the edge between the 2 colours is antialiased by the
render.

The work around with adding edges is only a workaround exactly as you
remarked because it doesn't work well with non transparent surfaces.

best
Jens

···

On Wed, 11 Nov 2015 at 13:44 Remo Goetschi <surf at libecciu.ch> wrote:

Hi,

Does somebody know how to produce a good-looking filled contour plot
with semi-transparent colors? If contourf() is passed a colormap with
semi-transparent colors, it produces small gaps between the filled areas:
http://i.stack.imgur.com/eEQXI.png

According to the docs, this is not a bug ("contourf() [...] does not
draw the polygon edges"). To draw the edges, it is suggested to "add
line contours with calls to contour()". But that doesn't look good
either as the edges become too opaque:
http://i.stack.imgur.com/s17F9.png
You can play with the linewidth argument of contour(), but that doesn't
help much. Any ideas?

The code that reproduces the problem is attached below (I use the
object-oriented API, but the result is the same with pyplot).

BTW, pcolormesh() suffers from a similar problem:
http://i.stack.imgur.com/Gbwcb.png

Both problems do not seem to occur with the SVG backend.

I asked the same question already on stackoverflow. Feel free to respond
there:

python - Matplotlib: filled contour plot with transparent colors - Stack Overflow

Thanks,
Remo

---------
import matplotlib
import numpy as np
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg

# generate some data
shape = (100, 100)
x_rng = np.linspace(-1, 1, shape[1])
y_rng = np.linspace(-1, 1, shape[0])
x, y = np.meshgrid(x_rng, y_rng)
z = np.sqrt(x**2 + y**2)

# create figure
width_inch, height_inch = 5, 5 # results in 500x500px with dpi=100
fig = Figure()
fig.set_size_inches((width_inch, height_inch))
FigureCanvasAgg(fig)
ax = fig.add_axes([0., 0., 1., 1.])
ax.set_axis_off()

# define some colors with alpha < 1
alpha = 0.9
colors = [
    (0.1, 0.1, 0.5, alpha), # dark blue
    (0.0, 0.7, 0.3, alpha), # green
    (0.9, 0.2, 0.7, alpha), # pink
    (0.0, 0.0, 0.0, alpha), # black
    (0.1, 0.7, 0.7, alpha), # light blue
]
cmap = matplotlib.colors.ListedColormap(colors)
levels = np.array(np.linspace(0, z.max(), len(colors)))
norm = matplotlib.colors.BoundaryNorm(levels, ncolors=cmap.N)

# contourf plot produces small gaps between filled areas
cnt = ax.contourf(x, y, z, levels, cmap=cmap, norm=norm,
                  antialiased=True, linecolor='none')

# this fills the gaps, but it makes them too opaque
# ax.contour(x, y, z, levels, cmap=cmap, norm=norm,
# antialiased=True)

# the same is true for this trick:
# for c in cnt.collections:
# c.set_edgecolor("face")

filename = "/tmp/contourf.png"
fig.savefig(filename, dpi=100, transparent=True, format="png")
print("Saved plot to {}.".format(filename))
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
Matplotlib-users Info Page

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-users/attachments/20151111/5b9d61e3/attachment.html&gt;

Hi,

Thanks for your response. Hm, are you saying there is probably no way to
work around this?
Are there other opinions?

Personally, I consider this a bug (or two bugs, since pcolormesh() has a
problem as well). It looks really ugly if you, e.g., use
semi-transparent plots as map overlays.

Cheers,
Remo

···

On 11.11.2015 15:53, Jens Nielsen wrote:

The issue you are seeing is slightly different from the one the docs
mention.
I wrote the docs suggesting the work around and this is mainly relevant
for vector backends (PDF and so on) The problem with PDF viewers is that
many of them create visible gaps when two polygons are rendered next to
each other with zero overlap. This is a viewer specific thing but lots
of viewers suffers from this.
This effect is much more visible that the one you see. I think the one
you see is due to the way the edge between the 2 colours is antialiased
by the render.

The work around with adding edges is only a workaround exactly as you
remarked because it doesn't work well with non transparent surfaces.

best
Jens

On Wed, 11 Nov 2015 at 13:44 Remo Goetschi <surf at libecciu.ch > <mailto:surf at libecciu.ch>> wrote:

    Hi,

    Does somebody know how to produce a good-looking filled contour plot
    with semi-transparent colors? If contourf() is passed a colormap with
    semi-transparent colors, it produces small gaps between the filled
    areas:
    http://i.stack.imgur.com/eEQXI.png

    According to the docs, this is not a bug ("contourf() [...] does not
    draw the polygon edges"). To draw the edges, it is suggested to "add
    line contours with calls to contour()". But that doesn't look good
    either as the edges become too opaque:
    http://i.stack.imgur.com/s17F9.png
    You can play with the linewidth argument of contour(), but that doesn't
    help much. Any ideas?

    The code that reproduces the problem is attached below (I use the
    object-oriented API, but the result is the same with pyplot).

    BTW, pcolormesh() suffers from a similar problem:
    http://i.stack.imgur.com/Gbwcb.png

    Both problems do not seem to occur with the SVG backend.

    I asked the same question already on stackoverflow. Feel free to respond
    there:
    python - Matplotlib: filled contour plot with transparent colors - Stack Overflow

    Thanks,
    Remo

    ---------
    import matplotlib
    import numpy as np
    from matplotlib.figure import Figure
    from matplotlib.backends.backend_agg import FigureCanvasAgg

    # generate some data
    shape = (100, 100)
    x_rng = np.linspace(-1, 1, shape[1])
    y_rng = np.linspace(-1, 1, shape[0])
    x, y = np.meshgrid(x_rng, y_rng)
    z = np.sqrt(x**2 + y**2)

    # create figure
    width_inch, height_inch = 5, 5 # results in 500x500px with dpi=100
    fig = Figure()
    fig.set_size_inches((width_inch, height_inch))
    FigureCanvasAgg(fig)
    ax = fig.add_axes([0., 0., 1., 1.])
    ax.set_axis_off()

    # define some colors with alpha < 1
    alpha = 0.9
    colors = [
        (0.1, 0.1, 0.5, alpha), # dark blue
        (0.0, 0.7, 0.3, alpha), # green
        (0.9, 0.2, 0.7, alpha), # pink
        (0.0, 0.0, 0.0, alpha), # black
        (0.1, 0.7, 0.7, alpha), # light blue
    ]
    cmap = matplotlib.colors.ListedColormap(colors)
    levels = np.array(np.linspace(0, z.max(), len(colors)))
    norm = matplotlib.colors.BoundaryNorm(levels, ncolors=cmap.N)

    # contourf plot produces small gaps between filled areas
    cnt = ax.contourf(x, y, z, levels, cmap=cmap, norm=norm,
                      antialiased=True, linecolor='none')

    # this fills the gaps, but it makes them too opaque
    # ax.contour(x, y, z, levels, cmap=cmap, norm=norm,
    # antialiased=True)

    # the same is true for this trick:
    # for c in cnt.collections:
    # c.set_edgecolor("face")

    filename = "/tmp/contourf.png"
    fig.savefig(filename, dpi=100, transparent=True, format="png")
    print("Saved plot to {}.".format(filename))
    _______________________________________________
    Matplotlib-users mailing list
    Matplotlib-users at python.org <mailto:Matplotlib-users at python.org>
    Matplotlib-users Info Page

Remo,

I certainly do consider this a bug, however, it is one of those rare
situations where we just can't seem to figure out how to fix it. We have
made attempts before and it has had some limited success, particularly in
the colorbar situation which goes through similar code paths in AGG. I
would certainly love to see it get totally fixed, as it is an unsightly
wart in the library.

I think the main problem is that there aren't enough people who are experts
in the AGG library that could either tell us what we are doing wrong in
using AGG, or recognize the problem and propose a patch that would fix the
problem in AGG (assuming that the problem is even located there). For all
we know, the problem could be in our path-handling code. As it stands right
now, the core devs probably just simply have too much on their plate to
hunt this particular one down at this time. If someone else can figure this
problem out, we would accept the patch in a heartbeat.

Ben Root

···

On Thu, Nov 12, 2015 at 4:07 AM, Remo Goetschi <surf at libecciu.ch> wrote:

Hi,

Thanks for your response. Hm, are you saying there is probably no way to
work around this?
Are there other opinions?

Personally, I consider this a bug (or two bugs, since pcolormesh() has a
problem as well). It looks really ugly if you, e.g., use
semi-transparent plots as map overlays.

Cheers,
Remo

On 11.11.2015 15:53, Jens Nielsen wrote:
> The issue you are seeing is slightly different from the one the docs
> mention.
> I wrote the docs suggesting the work around and this is mainly relevant
> for vector backends (PDF and so on) The problem with PDF viewers is that
> many of them create visible gaps when two polygons are rendered next to
> each other with zero overlap. This is a viewer specific thing but lots
> of viewers suffers from this.
> This effect is much more visible that the one you see. I think the one
> you see is due to the way the edge between the 2 colours is antialiased
> by the render.
>
> The work around with adding edges is only a workaround exactly as you
> remarked because it doesn't work well with non transparent surfaces.
>
> best
> Jens
>
> On Wed, 11 Nov 2015 at 13:44 Remo Goetschi <surf at libecciu.ch > > <mailto:surf at libecciu.ch>> wrote:
>
> Hi,
>
> Does somebody know how to produce a good-looking filled contour plot
> with semi-transparent colors? If contourf() is passed a colormap with
> semi-transparent colors, it produces small gaps between the filled
> areas:
> http://i.stack.imgur.com/eEQXI.png
>
> According to the docs, this is not a bug ("contourf() [...] does not
> draw the polygon edges"). To draw the edges, it is suggested to "add
> line contours with calls to contour()". But that doesn't look good
> either as the edges become too opaque:
> http://i.stack.imgur.com/s17F9.png
> You can play with the linewidth argument of contour(), but that
doesn't
> help much. Any ideas?
>
> The code that reproduces the problem is attached below (I use the
> object-oriented API, but the result is the same with pyplot).
>
> BTW, pcolormesh() suffers from a similar problem:
> http://i.stack.imgur.com/Gbwcb.png
>
> Both problems do not seem to occur with the SVG backend.
>
> I asked the same question already on stackoverflow. Feel free to
respond
> there:
>
python - Matplotlib: filled contour plot with transparent colors - Stack Overflow
>
> Thanks,
> Remo
>
> ---------
> import matplotlib
> import numpy as np
> from matplotlib.figure import Figure
> from matplotlib.backends.backend_agg import FigureCanvasAgg
>
> # generate some data
> shape = (100, 100)
> x_rng = np.linspace(-1, 1, shape[1])
> y_rng = np.linspace(-1, 1, shape[0])
> x, y = np.meshgrid(x_rng, y_rng)
> z = np.sqrt(x**2 + y**2)
>
> # create figure
> width_inch, height_inch = 5, 5 # results in 500x500px with dpi=100
> fig = Figure()
> fig.set_size_inches((width_inch, height_inch))
> FigureCanvasAgg(fig)
> ax = fig.add_axes([0., 0., 1., 1.])
> ax.set_axis_off()
>
> # define some colors with alpha < 1
> alpha = 0.9
> colors = [
> (0.1, 0.1, 0.5, alpha), # dark blue
> (0.0, 0.7, 0.3, alpha), # green
> (0.9, 0.2, 0.7, alpha), # pink
> (0.0, 0.0, 0.0, alpha), # black
> (0.1, 0.7, 0.7, alpha), # light blue
> ]
> cmap = matplotlib.colors.ListedColormap(colors)
> levels = np.array(np.linspace(0, z.max(), len(colors)))
> norm = matplotlib.colors.BoundaryNorm(levels, ncolors=cmap.N)
>
> # contourf plot produces small gaps between filled areas
> cnt = ax.contourf(x, y, z, levels, cmap=cmap, norm=norm,
> antialiased=True, linecolor='none')
>
> # this fills the gaps, but it makes them too opaque
> # ax.contour(x, y, z, levels, cmap=cmap, norm=norm,
> # antialiased=True)
>
> # the same is true for this trick:
> # for c in cnt.collections:
> # c.set_edgecolor("face")
>
> filename = "/tmp/contourf.png"
> fig.savefig(filename, dpi=100, transparent=True, format="png")
> print("Saved plot to {}.".format(filename))
> _______________________________________________
> Matplotlib-users mailing list
> Matplotlib-users at python.org <mailto:Matplotlib-users at python.org>
> Matplotlib-users Info Page
>

_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
Matplotlib-users Info Page

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-users/attachments/20151113/ecd1d148/attachment.html&gt;

Hi,

Does somebody know how to produce a good-looking filled contour plot
with semi-transparent colors? If contourf() is passed a colormap with
semi-transparent colors, it produces small gaps between the filled areas:
http://i.stack.imgur.com/eEQXI.png

There are potentially two problems, depending on whether anti-aliasing
is on.

Without anti-aliasing, the fundamental problem is how pixels are filled
in adjacent patches with a common boundary specified as floating point.
This should be solvable, but it might be down in the darkest corners of agg.

With anti-aliasing, I think the problem is inherent and has no solution,
thought there might be ways its visual effect could be reduced in common
cases. The problem here is that antialiasing fuzzes the boundary by
fading out pixels depending on how much of the pixel is outside a patch.
  With alpha not equal to one, this means that the background, and
anything plotted earlier, shows through. Therefore the end result
depends on the background color, and will in general not be just a blend
of the two colors of the adjacent patches, which is what one intended.
It can be darker or lighter, etc.

I think that in other filled contour implementations (Matlab, Ferret)
the problems we see in mpl with some renderers even with no transparency
and no antialiasing are absent because they build a stack of
superimposed filled regions instead of adjacent regions. We could
provide an option to do this.

Eric

···

On 2015/11/11 3:28 AM, Remo Goetschi wrote:

According to the docs, this is not a bug ("contourf() [...] does not
draw the polygon edges"). To draw the edges, it is suggested to "add
line contours with calls to contour()". But that doesn't look good
either as the edges become too opaque:
http://i.stack.imgur.com/s17F9.png
You can play with the linewidth argument of contour(), but that doesn't
help much. Any ideas?

The code that reproduces the problem is attached below (I use the
object-oriented API, but the result is the same with pyplot).

BTW, pcolormesh() suffers from a similar problem:
http://i.stack.imgur.com/Gbwcb.png

Both problems do not seem to occur with the SVG backend.

I asked the same question already on stackoverflow. Feel free to respond
there:
python - Matplotlib: filled contour plot with transparent colors - Stack Overflow

Thanks,
Remo

---------
import matplotlib
import numpy as np
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg

# generate some data
shape = (100, 100)
x_rng = np.linspace(-1, 1, shape[1])
y_rng = np.linspace(-1, 1, shape[0])
x, y = np.meshgrid(x_rng, y_rng)
z = np.sqrt(x**2 + y**2)

# create figure
width_inch, height_inch = 5, 5 # results in 500x500px with dpi=100
fig = Figure()
fig.set_size_inches((width_inch, height_inch))
FigureCanvasAgg(fig)
ax = fig.add_axes([0., 0., 1., 1.])
ax.set_axis_off()

# define some colors with alpha < 1
alpha = 0.9
colors = [
     (0.1, 0.1, 0.5, alpha), # dark blue
     (0.0, 0.7, 0.3, alpha), # green
     (0.9, 0.2, 0.7, alpha), # pink
     (0.0, 0.0, 0.0, alpha), # black
     (0.1, 0.7, 0.7, alpha), # light blue
]
cmap = matplotlib.colors.ListedColormap(colors)
levels = np.array(np.linspace(0, z.max(), len(colors)))
norm = matplotlib.colors.BoundaryNorm(levels, ncolors=cmap.N)

# contourf plot produces small gaps between filled areas
cnt = ax.contourf(x, y, z, levels, cmap=cmap, norm=norm,
                   antialiased=True, linecolor='none')

# this fills the gaps, but it makes them too opaque
# ax.contour(x, y, z, levels, cmap=cmap, norm=norm,
# antialiased=True)

# the same is true for this trick:
# for c in cnt.collections:
# c.set_edgecolor("face")

filename = "/tmp/contourf.png"
fig.savefig(filename, dpi=100, transparent=True, format="png")
print("Saved plot to {}.".format(filename))
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
Matplotlib-users Info Page

Hi Eric and Ben

Thanks a lot for your elaborations on this problem. I am a non-expert in
both agg and matplotlib development. On the other hand, this issue is a
serious problem for us and we have some motivation to solve it.

I think that in other filled contour implementations (Matlab, Ferret)
the problems we see in mpl with some renderers even with no
transparency and no antialiasing are absent because they build a
stack of superimposed filled regions instead of adjacent regions. We
could provide an option to do this.

To me, that sounds like a reasonable solution.

What's a good way to start? Open an issue on github?

Cheers,
Remo

···

On 13.11.2015 19:08, Eric Firing wrote:

On 13.11.2015 19:08, Eric Firing wrote:

On 2015/11/11 3:28 AM, Remo Goetschi wrote:

Hi,

Does somebody know how to produce a good-looking filled contour plot
with semi-transparent colors? If contourf() is passed a colormap with
semi-transparent colors, it produces small gaps between the filled areas:
http://i.stack.imgur.com/eEQXI.png

There are potentially two problems, depending on whether anti-aliasing
is on.

Without anti-aliasing, the fundamental problem is how pixels are filled
in adjacent patches with a common boundary specified as floating point.
This should be solvable, but it might be down in the darkest corners of
agg.

With anti-aliasing, I think the problem is inherent and has no solution,
thought there might be ways its visual effect could be reduced in common
cases. The problem here is that antialiasing fuzzes the boundary by
fading out pixels depending on how much of the pixel is outside a patch.
With alpha not equal to one, this means that the background, and
anything plotted earlier, shows through. Therefore the end result
depends on the background color, and will in general not be just a blend
of the two colors of the adjacent patches, which is what one intended.
It can be darker or lighter, etc.

I think that in other filled contour implementations (Matlab, Ferret)
the problems we see in mpl with some renderers even with no transparency
and no antialiasing are absent because they build a stack of
superimposed filled regions instead of adjacent regions. We could
provide an option to do this.

Eric

According to the docs, this is not a bug ("contourf() [...] does not
draw the polygon edges"). To draw the edges, it is suggested to "add
line contours with calls to contour()". But that doesn't look good
either as the edges become too opaque:
http://i.stack.imgur.com/s17F9.png
You can play with the linewidth argument of contour(), but that doesn't
help much. Any ideas?

The code that reproduces the problem is attached below (I use the
object-oriented API, but the result is the same with pyplot).

BTW, pcolormesh() suffers from a similar problem:
http://i.stack.imgur.com/Gbwcb.png

Both problems do not seem to occur with the SVG backend.

I asked the same question already on stackoverflow. Feel free to respond
there:
python - Matplotlib: filled contour plot with transparent colors - Stack Overflow

Thanks,
Remo

---------
import matplotlib
import numpy as np
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg

# generate some data
shape = (100, 100)
x_rng = np.linspace(-1, 1, shape[1])
y_rng = np.linspace(-1, 1, shape[0])
x, y = np.meshgrid(x_rng, y_rng)
z = np.sqrt(x**2 + y**2)

# create figure
width_inch, height_inch = 5, 5 # results in 500x500px with dpi=100
fig = Figure()
fig.set_size_inches((width_inch, height_inch))
FigureCanvasAgg(fig)
ax = fig.add_axes([0., 0., 1., 1.])
ax.set_axis_off()

# define some colors with alpha < 1
alpha = 0.9
colors = [
     (0.1, 0.1, 0.5, alpha), # dark blue
     (0.0, 0.7, 0.3, alpha), # green
     (0.9, 0.2, 0.7, alpha), # pink
     (0.0, 0.0, 0.0, alpha), # black
     (0.1, 0.7, 0.7, alpha), # light blue
]
cmap = matplotlib.colors.ListedColormap(colors)
levels = np.array(np.linspace(0, z.max(), len(colors)))
norm = matplotlib.colors.BoundaryNorm(levels, ncolors=cmap.N)

# contourf plot produces small gaps between filled areas
cnt = ax.contourf(x, y, z, levels, cmap=cmap, norm=norm,
                   antialiased=True, linecolor='none')

# this fills the gaps, but it makes them too opaque
# ax.contour(x, y, z, levels, cmap=cmap, norm=norm,
# antialiased=True)

# the same is true for this trick:
# for c in cnt.collections:
# c.set_edgecolor("face")

filename = "/tmp/contourf.png"
fig.savefig(filename, dpi=100, transparent=True, format="png")
print("Saved plot to {}.".format(filename))
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
Matplotlib-users Info Page

_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
Matplotlib-users Info Page

Hi Eric and Ben

Thanks a lot for your elaborations on this problem. I am a non-expert in
both agg and matplotlib development. On the other hand, this issue is a
serious problem for us and we have some motivation to solve it.

I think that in other filled contour implementations (Matlab, Ferret)
the problems we see in mpl with some renderers even with no
transparency and no antialiasing are absent because they build a
stack of superimposed filled regions instead of adjacent regions. We
could provide an option to do this.

To me, that sounds like a reasonable solution.

What's a good way to start? Open an issue on github?

You could open a "wishlist" issue, referring to this email thread,
requesting the stacking option above. I don't think it would be
difficult to implement, but I might be missing something.

However...I'm not sure it would do what you want in the case of
*transparent* colors. If you stack transparent colors, what you get is
a blend with everything underneath. Is this what you want?

Can you supply examples of the desired result, produced by some other
plotting software?

Eric

···

On 2015/11/16 10:13 PM, Remo Goetschi wrote:

On 13.11.2015 19:08, Eric Firing wrote:

Cheers,
Remo

On 13.11.2015 19:08, Eric Firing wrote:

On 2015/11/11 3:28 AM, Remo Goetschi wrote:

Hi,

Does somebody know how to produce a good-looking filled contour plot
with semi-transparent colors? If contourf() is passed a colormap with
semi-transparent colors, it produces small gaps between the filled areas:
http://i.stack.imgur.com/eEQXI.png

There are potentially two problems, depending on whether anti-aliasing
is on.

Without anti-aliasing, the fundamental problem is how pixels are filled
in adjacent patches with a common boundary specified as floating point.
This should be solvable, but it might be down in the darkest corners of
agg.

With anti-aliasing, I think the problem is inherent and has no solution,
thought there might be ways its visual effect could be reduced in common
cases. The problem here is that antialiasing fuzzes the boundary by
fading out pixels depending on how much of the pixel is outside a patch.
  With alpha not equal to one, this means that the background, and
anything plotted earlier, shows through. Therefore the end result
depends on the background color, and will in general not be just a blend
of the two colors of the adjacent patches, which is what one intended.
It can be darker or lighter, etc.

I think that in other filled contour implementations (Matlab, Ferret)
the problems we see in mpl with some renderers even with no transparency
and no antialiasing are absent because they build a stack of
superimposed filled regions instead of adjacent regions. We could
provide an option to do this.

Eric

According to the docs, this is not a bug ("contourf() [...] does not
draw the polygon edges"). To draw the edges, it is suggested to "add
line contours with calls to contour()". But that doesn't look good
either as the edges become too opaque:
http://i.stack.imgur.com/s17F9.png
You can play with the linewidth argument of contour(), but that doesn't
help much. Any ideas?

The code that reproduces the problem is attached below (I use the
object-oriented API, but the result is the same with pyplot).

BTW, pcolormesh() suffers from a similar problem:
http://i.stack.imgur.com/Gbwcb.png

Both problems do not seem to occur with the SVG backend.

I asked the same question already on stackoverflow. Feel free to respond
there:
python - Matplotlib: filled contour plot with transparent colors - Stack Overflow

Thanks,
Remo

---------
import matplotlib
import numpy as np
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg

# generate some data
shape = (100, 100)
x_rng = np.linspace(-1, 1, shape[1])
y_rng = np.linspace(-1, 1, shape[0])
x, y = np.meshgrid(x_rng, y_rng)
z = np.sqrt(x**2 + y**2)

# create figure
width_inch, height_inch = 5, 5 # results in 500x500px with dpi=100
fig = Figure()
fig.set_size_inches((width_inch, height_inch))
FigureCanvasAgg(fig)
ax = fig.add_axes([0., 0., 1., 1.])
ax.set_axis_off()

# define some colors with alpha < 1
alpha = 0.9
colors = [
      (0.1, 0.1, 0.5, alpha), # dark blue
      (0.0, 0.7, 0.3, alpha), # green
      (0.9, 0.2, 0.7, alpha), # pink
      (0.0, 0.0, 0.0, alpha), # black
      (0.1, 0.7, 0.7, alpha), # light blue
]
cmap = matplotlib.colors.ListedColormap(colors)
levels = np.array(np.linspace(0, z.max(), len(colors)))
norm = matplotlib.colors.BoundaryNorm(levels, ncolors=cmap.N)

# contourf plot produces small gaps between filled areas
cnt = ax.contourf(x, y, z, levels, cmap=cmap, norm=norm,
                    antialiased=True, linecolor='none')

# this fills the gaps, but it makes them too opaque
# ax.contour(x, y, z, levels, cmap=cmap, norm=norm,
# antialiased=True)

# the same is true for this trick:
# for c in cnt.collections:
# c.set_edgecolor("face")

filename = "/tmp/contourf.png"
fig.savefig(filename, dpi=100, transparent=True, format="png")
print("Saved plot to {}.".format(filename))
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
Matplotlib-users Info Page

_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
Matplotlib-users Info Page

_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
Matplotlib-users Info Page