Uniform transparency and background color?

Hello,

Is it possible to specify both an alpha level and a background color so
that an entire saved image has a uniform transparency and color? For
example, with matplotlib 1.0.0, this script yields the attached image:

from matplotlib.pyplot import figure, savefig, show

fig = figure()
ax = fig.add_subplot(111)
ax.plot([1,2,3])

fig.patch.set_alpha(0.5)
for ax in fig.axes:
    ax.patch.set_alpha(0.5)

fig.patch.set_facecolor('red')
for ax in fig.axes:
    ax.patch.set_facecolor('red')

savefig('test.png', facecolor='red')

In particular, the areas inside and outside the axes have different
transparency level and color. Perhaps I'm over/mis/ab-using the options
here?

Thanks for your great software and any help you can provide!

Sincerely,
Mitesh Patel

test.png

It's not that they're not uniform--you're seeing alpha blending
between the figure patch and the axes patch. Within the axes, both are
being rendered and blended together. This is more readily apparent if
you use blue for the axes patch, as I did for the attached image. When
the red and blue are blended together, you end up with purple. If you
want it all uniform, you'd be better off setting the axes patch to an
alpha of 0.0.

Ryan

test.png

···

On Thu, Sep 2, 2010 at 2:15 AM, Mitesh Patel <qed777@...287...> wrote:

Hello,

Is it possible to specify both an alpha level and a background color so
that an entire saved image has a uniform transparency and color? For
example, with matplotlib 1.0.0, this script yields the attached image:

from matplotlib.pyplot import figure, savefig, show

fig = figure()
ax = fig.add_subplot(111)
ax.plot([1,2,3])

fig.patch.set_alpha(0.5)
for ax in fig.axes:
ax.patch.set_alpha(0.5)

fig.patch.set_facecolor('red')
for ax in fig.axes:
ax.patch.set_facecolor('red')

savefig('test.png', facecolor='red')

In particular, the areas inside and outside the axes have different
transparency level and color. Perhaps I'm over/mis/ab-using the options
here?

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma

Mitesh,

That is an interesting idea. Theoretically, it might be possible to implement such a feature. The key design idea of Matplotlib is to have Artist objects that own other Artist objects. So, a Figure owns several axes, and those axes own various plotting elements, which are all subclasses of Artists. So, I could imagine that an rgba value could get “inherited” by a child artist from its parent (unless the user specifies differently).

Would we want to automatically make text inherit the rgba setting? Also, currently there are a lot of places in code where one directly specifies color, or color is automatically chosen (from a colormap or a rotating set of colors). I wonder what should be the proper behavior in those cases (ignore parent setting? if so, then do the setting still get passed on to child artists? should the automatically chosen settings get passed on?).

What do others think?

Ben Root

···

On Thu, Sep 2, 2010 at 2:15 AM, Mitesh Patel <qed777@…287…> wrote:

Hello,

Is it possible to specify both an alpha level and a background color so

that an entire saved image has a uniform transparency and color? For

example, with matplotlib 1.0.0, this script yields the attached image:

from matplotlib.pyplot import figure, savefig, show

fig = figure()

ax = fig.add_subplot(111)

ax.plot([1,2,3])

fig.patch.set_alpha(0.5)

for ax in fig.axes:

ax.patch.set_alpha(0.5)

fig.patch.set_facecolor(‘red’)

for ax in fig.axes:

ax.patch.set_facecolor('red')

savefig(‘test.png’, facecolor=‘red’)

In particular, the areas inside and outside the axes have different

transparency level and color. Perhaps I’m over/mis/ab-using the options

here?

Thanks for your great software and any help you can provide!

Sincerely,

Mitesh Patel

This also raises another pet peeve of mine. The Agg backend seems to use linear blending for alpha. This is inconsistent with how the world works. It is more realistic for logarithmic blending, or at least, a piece-wise linear blending.

Imagine I have two overlapping objects with alpha set to .5 (a_1 and a_2). What is rendered in matplotlib is completely opaque. A more realistic result would have a final alpha setting of .75 (i.e. - the first item takes away half the transparency, then the second item takes away half of the remaining transparency.

I am not nearly familiar enough with the Agg backend to know how to implement this. Is this at all feasible?

Ben Root

···

On Thu, Sep 2, 2010 at 9:11 AM, Ryan May <rmay31@…287…> wrote:

On Thu, Sep 2, 2010 at 2:15 AM, Mitesh Patel <qed777@…287…> wrote:

Hello,

Is it possible to specify both an alpha level and a background color so

that an entire saved image has a uniform transparency and color? For

example, with matplotlib 1.0.0, this script yields the attached image:

from matplotlib.pyplot import figure, savefig, show

fig = figure()

ax = fig.add_subplot(111)

ax.plot([1,2,3])

fig.patch.set_alpha(0.5)

for ax in fig.axes:

ax.patch.set_alpha(0.5)

fig.patch.set_facecolor(‘red’)

for ax in fig.axes:

ax.patch.set_facecolor(‘red’)

savefig(‘test.png’, facecolor=‘red’)

In particular, the areas inside and outside the axes have different

transparency level and color. Perhaps I’m over/mis/ab-using the options

here?

It’s not that they’re not uniform–you’re seeing alpha blending

between the figure patch and the axes patch. Within the axes, both are

being rendered and blended together. This is more readily apparent if

you use blue for the axes patch, as I did for the attached image. When

the red and blue are blended together, you end up with purple. If you

want it all uniform, you’d be better off setting the axes patch to an

alpha of 0.0.

Ryan

I'm not sure this is what's going on. Right now, though, I'm seeing
some weird draw artifacts that I don't have time to run down. What I
will say is that while some other blending functions may be
interesting, I don't think it's widely supported. OpenGL just treats
the alpha as a weight for the colors. You can tweak it, but it's
inherently linear unless you write a pixel shader.

Also, I don't think the blending produces an opaque result. I'm pretty
sure you can blend 3 colors together, each with an alpha > 0.5. The
color will be pretty saturated, but opaque would mean the bottom color
doesn't show through. (I'll hack on an example later). Remember,
though, that your monitor doesn't display an "alpha" color. Any
translucency from a net blending of colors just means that you're
blending in a background color (alpha=1.0) somewhere.

Ryan

···

On Thu, Sep 2, 2010 at 9:23 AM, Benjamin Root <ben.root@...1304...> wrote:

This also raises another pet peeve of mine. The Agg backend seems to use
linear blending for alpha. This is inconsistent with how the world works.
It is more realistic for logarithmic blending, or at least, a piece-wise
linear blending.

Imagine I have two overlapping objects with alpha set to .5 (a_1 and a_2).
What is rendered in matplotlib is completely opaque. A more realistic
result would have a final alpha setting of .75 (i.e. - the first item takes
away half the transparency, then the second item takes away half of the
remaining transparency.

I am not nearly familiar enough with the Agg backend to know how to
implement this. Is this at all feasible?

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma

The problem is that then the other backends (PDF, SVG etc) would have
different alpha blending behavior. If that can be resolved, then I
think getting Agg to handle logarithmic blending is the easy part.

Mike

···
-- Michael Droettboom
Science Software Branch
Space Telescope Science Institute
Baltimore, Maryland, USA