[Matplotlib-users] contourf looking ugly with transparent colors

Remo Goetschi surf at libecciu.ch
Tue Nov 17 03:13:25 EST 2015


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.

On 13.11.2015 19:08, Eric Firing wrote:
> 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 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:
>> 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))
>> _______________________________________________
>> Matplotlib-users mailing list
>> Matplotlib-users at python.org
>> https://mail.python.org/mailman/listinfo/matplotlib-users
>>
> 
> _______________________________________________
> Matplotlib-users mailing list
> Matplotlib-users at python.org
> https://mail.python.org/mailman/listinfo/matplotlib-users



More information about the Matplotlib-users mailing list