Transparency with fig.canvas.mpl_connect

Hi All,

I'm a new matplotlib user on a Windows XP machine running mpl0.99.0 under
Python 2.5. I'm using the default rc file.

While reading through the excellent matplotlib "how-to" tutorial
(http://matplotlib.sourceforge.net/faq/howto_faq.html), I came across two
useful scripts: one to save a figure with a transparent background, and one
to resize axes automatically so that labels aren't cut off. I was able to
run both these examples given on the "how-to" successfully.

However, I ran into trouble when trying to combine them as follows:

···

=====

import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10))
ax.set_yticks((2,5,7))
labels = ax.set_yticklabels(('really, really, really', 'long', 'labels'))

def on_draw(event):
    bboxes = []
    for label in labels:
        bbox = label.get_window_extent()
        # the figure transform goes from relative coords->pixels and we
        # want the inverse of that
        bboxi = bbox.inverse_transformed(fig.transFigure)
        bboxes.append(bboxi)

    # this is the bbox that bounds all the bboxes, again in relative
    # figure coords
    bbox = mtransforms.Bbox.union(bboxes)
    if fig.subplotpars.left < bbox.width:
        # we need to move it over
        fig.subplots_adjust(left=1.1*bbox.width) # pad a little
        fig.canvas.draw()
        
    return False

fig.canvas.mpl_connect('draw_event', on_draw)

plt.savefig('test.png', transparent=True)

=====

In this case, the saved png file is transparent, but the original set of
axes, labels, and plot are visible as well (basically, I have two identical
plots shifted over one another on a transparent background).

Is there a way to suppress the original output (something akin to
"fig.canvas.erase()" or "fig.canvas.clear()", but I can't seem to figure it
out) so that the output png only shows the shifted axes and not both sets?

Thanks in advance!
Brian
--
View this message in context: http://old.nabble.com/Transparency-with-fig.canvas.mpl_connect-tp27724532p27724532.html
Sent from the matplotlib - users mailing list archive at Nabble.com.

Interesting! That one really surprised me. It turns out mpl is not
clearing the pixel buffer from the previous draw command. Normally
you don't see this because the call to draw the figure.patch blanks
out the pixel buffer with the background color, but since your figure
patch is transparent you can see the legacy. A call to
renderer.clear() before drawing again will erase the old image
(perhaps we should be doing this by default?)

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10))
ax.set_yticks((2,5,7))
labels = ax.set_yticklabels(('really, really, really', 'long', 'labels'))

def on_draw(event):
   bboxes = []
   for label in labels:
       bbox = label.get_window_extent()
       # the figure transform goes from relative coords->pixels and we
       # want the inverse of that
       bboxi = bbox.inverse_transformed(fig.transFigure)
       bboxes.append(bboxi)

   # this is the bbox that bounds all the bboxes, again in relative
   # figure coords
   bbox = mtransforms.Bbox.union(bboxes)
   if fig.subplotpars.left < bbox.width:
       # we need to move it over
       fig.subplots_adjust(left=1.1*bbox.width) # pad a little
       fig.canvas.get_renderer().clear()
       fig.canvas.draw()

   return False

fig.canvas.mpl_connect('draw_event', on_draw)

plt.savefig('test.png', transparent=True)

JDH

···

On Fri, Feb 26, 2010 at 5:14 PM, brianjpetersen <brianjpetersen@...287...> wrote:

Hi All,

I'm a new matplotlib user on a Windows XP machine running mpl0.99.0 under
Python 2.5. I'm using the default rc file.

While reading through the excellent matplotlib "how-to" tutorial
(http://matplotlib.sourceforge.net/faq/howto_faq.html), I came across two
useful scripts: one to save a figure with a transparent background, and one
to resize axes automatically so that labels aren't cut off. I was able to
run both these examples given on the "how-to" successfully.

However, I ran into trouble when trying to combine them as follows:

=====

import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10))
ax.set_yticks((2,5,7))
labels = ax.set_yticklabels(('really, really, really', 'long', 'labels'))

def on_draw(event):
bboxes = []
for label in labels:
bbox = label.get_window_extent()
# the figure transform goes from relative coords->pixels and we
# want the inverse of that
bboxi = bbox.inverse_transformed(fig.transFigure)
bboxes.append(bboxi)

# this is the bbox that bounds all the bboxes, again in relative
# figure coords
bbox = mtransforms.Bbox.union(bboxes)
if fig.subplotpars.left < bbox.width:
# we need to move it over
fig.subplots_adjust(left=1.1*bbox.width) # pad a little
fig.canvas.draw()

return False

fig.canvas.mpl_connect('draw_event', on_draw)

plt.savefig('test.png', transparent=True)

=====

In this case, the saved png file is transparent, but the original set of
axes, labels, and plot are visible as well (basically, I have two identical
plots shifted over one another on a transparent background).

Is there a way to suppress the original output (something akin to
"fig.canvas.erase()" or "fig.canvas.clear()", but I can't seem to figure it
out) so that the output png only shows the shifted axes and not both sets?

Thanks so much John! That does the trick.

I'm just a new user of mpl, so your question about whether the default
behavior of draw should be changed is probably "above my pay grade." I just
don't know the API well enough to comment intelligently about it. That
said, I would suggest that this behavior be documented (either in the
tutorial page I originally accessed, the documentation for "canvas.draw()",
both locations, or some other appropriate place).

Thanks again from a very satisfied mpl user,
Brian

John Hunter-4 wrote:

···

On Fri, Feb 26, 2010 at 5:14 PM, brianjpetersen > <brianjpetersen@...287...> wrote:

Hi All,

I'm a new matplotlib user on a Windows XP machine running mpl0.99.0 under
Python 2.5. I'm using the default rc file.

While reading through the excellent matplotlib "how-to" tutorial
(http://matplotlib.sourceforge.net/faq/howto_faq.html), I came across two
useful scripts: one to save a figure with a transparent background, and
one
to resize axes automatically so that labels aren't cut off. I was able
to
run both these examples given on the "how-to" successfully.

However, I ran into trouble when trying to combine them as follows:

=====

import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10))
ax.set_yticks((2,5,7))
labels = ax.set_yticklabels(('really, really, really', 'long', 'labels'))

def on_draw(event):
bboxes = []
for label in labels:
bbox = label.get_window_extent()
# the figure transform goes from relative coords->pixels and we
# want the inverse of that
bboxi = bbox.inverse_transformed(fig.transFigure)
bboxes.append(bboxi)

# this is the bbox that bounds all the bboxes, again in relative
# figure coords
bbox = mtransforms.Bbox.union(bboxes)
if fig.subplotpars.left < bbox.width:
# we need to move it over
fig.subplots_adjust(left=1.1*bbox.width) # pad a little
fig.canvas.draw()

return False

fig.canvas.mpl_connect('draw_event', on_draw)

plt.savefig('test.png', transparent=True)

=====

In this case, the saved png file is transparent, but the original set of
axes, labels, and plot are visible as well (basically, I have two
identical
plots shifted over one another on a transparent background).

Is there a way to suppress the original output (something akin to
"fig.canvas.erase()" or "fig.canvas.clear()", but I can't seem to figure
it
out) so that the output png only shows the shifted axes and not both
sets?

Interesting! That one really surprised me. It turns out mpl is not
clearing the pixel buffer from the previous draw command. Normally
you don't see this because the call to draw the figure.patch blanks
out the pixel buffer with the background color, but since your figure
patch is transparent you can see the legacy. A call to
renderer.clear() before drawing again will erase the old image
(perhaps we should be doing this by default?)

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10))
ax.set_yticks((2,5,7))
labels = ax.set_yticklabels(('really, really, really', 'long', 'labels'))

def on_draw(event):
   bboxes = []
   for label in labels:
       bbox = label.get_window_extent()
       # the figure transform goes from relative coords->pixels and we
       # want the inverse of that
       bboxi = bbox.inverse_transformed(fig.transFigure)
       bboxes.append(bboxi)

   # this is the bbox that bounds all the bboxes, again in relative
   # figure coords
   bbox = mtransforms.Bbox.union(bboxes)
   if fig.subplotpars.left < bbox.width:
       # we need to move it over
       fig.subplots_adjust(left=1.1*bbox.width) # pad a little
       fig.canvas.get_renderer().clear()
       fig.canvas.draw()

   return False

fig.canvas.mpl_connect('draw_event', on_draw)

plt.savefig('test.png', transparent=True)

JDH

------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

--
View this message in context: http://old.nabble.com/Transparency-with-fig.canvas.mpl_connect-tp27724532p27738002.html
Sent from the matplotlib - users mailing list archive at Nabble.com.