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.
On Fri, Feb 26, 2010 at 5:14 PM, brianjpetersen <bri...@gm...> 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
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 > <bri...@gm...> 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® 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 > Mat...@li... > 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.