Re: [matplotlib-devel] tight subplot parameters
On 07/21/2010 05:26 PM, John Hunter wrote: On Wed, Jul 21, 2010 at 10:09 PM, Tony S Yutsy...@gmail.com wrote: Wow, I don't see that at all. I'm on OS X, mpl svn HEAD (r8567), and Qt4Agg. I don't have GTK installed, so unfortunately, I can't really do a proper comparison. Here's the output I get from your modified script. I get something similar with TkAgg (unfortunately, I get an AttributeError with the macosx backend). Works on my system for tkagg and qtagg4, so the bug appears gtkagg specific. Must be something in the draw vs window realized and sized pipeline. It appears you are getting some bogus size info.Wonder if connecting to the draw_event might help here (longshot) or if any any of Eric's recent work on show is impacting th behavior here. No. I modified the script to eliminate the subplots() calls so that I could run it on 0.99.3 (the first 2 figures only), and it still doesn't work on gtkagg, but does work on qt4agg. Eric -- This SF.net email is sponsored by Sprint What will you do first with EVO, the first 4G phone? Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] tight subplot parameters
On 07/21/2010 05:26 PM, John Hunter wrote: On Wed, Jul 21, 2010 at 10:09 PM, Tony S Yutsy...@gmail.com wrote: Wow, I don't see that at all. I'm on OS X, mpl svn HEAD (r8567), and Qt4Agg. I don't have GTK installed, so unfortunately, I can't really do a proper comparison. Here's the output I get from your modified script. I get something similar with TkAgg (unfortunately, I get an AttributeError with the macosx backend). Works on my system for tkagg and qtagg4, so the bug appears gtkagg specific. Must be something in the draw vs window realized and sized pipeline. It appears you are getting some bogus size info.Wonder if connecting to the draw_event might help here (longshot) or if any any of Eric's recent work on show is impacting th behavior here. It is not anything I changed, but it is related to when drawing occurs. The following change makes it work with gtk, and keep working with qt4agg: efir...@manini:~/temp$ diff -u tight_layout.py tight_layout_gtk.py --- tight_layout.py 2010-07-21 20:28:16.0 -1000 +++ tight_layout_gtk.py 2010-07-21 20:29:05.0 -1000 @@ -131,6 +131,7 @@ if __name__ == '__main__': import numpy as np np.random.seed(1234) +plt.ion() fontsizes = [8, 16, 24, 32] def example_plot(ax): ax.plot([1, 2]) @@ -164,5 +165,6 @@ for ax in row: example_plot(ax) tight_layout() +plt.ioff() fig.savefig('tight5') plt.show() I have not tracked down the reason why gtk is behaving differently; drawing with gtkagg is a bit convoluted. It appears that gtk is more efficient in delaying drawing, and in drawing only once at the end, while the others are less clever, and actually draw when the canvas.draw() method is executed. Eric -- This SF.net email is sponsored by Sprint What will you do first with EVO, the first 4G phone? Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel -- This SF.net email is sponsored by Sprint What will you do first with EVO, the first 4G phone? Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] tight subplot parameters
--- On Wed, 7/21/10, Tony S Yu tsy...@gmail.com wrote: I get something similar with TkAgg (unfortunately, I get an AttributeError with the macosx backend). This is the AttributeError: Traceback (most recent call last): File Desktop/tight_layout.py, line 142, in module tight_layout() File Desktop/tight_layout.py, line 28, in tight_layout tight_subplot_spacing(fig, h_pad_inches, w_pad_inches) File Desktop/tight_layout.py, line 64, in tight_subplot_spacing ax_bottom, ax_top, ax_left, ax_right = _get_grid_boundaries(fig) File Desktop/tight_layout.py, line 99, in _get_grid_boundaries renderer = fig.canvas.get_renderer() AttributeError: 'FigureCanvasMac' object has no attribute 'get_renderer' Is a backend required to implement a get_renderer method? I only see it implemented in backend_agg.py, and it's missing in backend_bases.py, backend_template.py, backend_cairo.py, and in the macosx backend. If you want to try your code with the macosx backend, you can use fig.canvas.renderer instead of fig.canvas.get_renderer(). --Michiel. -- This SF.net email is sponsored by Sprint What will you do first with EVO, the first 4G phone? Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] tight subplot parameters
On Thu, Jul 22, 2010 at 7:40 AM, Michiel de Hoon mjldeh...@yahoo.com wrote: Is a backend required to implement a get_renderer method? I only see it implemented in backend_agg.py, and it's missing in backend_bases.py, backend_template.py, backend_cairo.py, and in the macosx backend. If you want to try your code with the macosx backend, you can use fig.canvas.renderer instead of fig.canvas.get_renderer(). According to backend_bases.FigureCanvas, a renderer attr is not guaranteed either. The Agg* backends rely on get_renderer so that they can get a properly sized renderer on figure resizes, dpi changes, etc. We could handle this on the agg side with a property, or require all canvases to supply get renderer. The tricky bit is that renderers may not be available until draw time for some backends, and thus may not have proper size information if accessed too early (this is probably at the heart of the gtk bug we are seeing). It is probably a good idea to settle on something so developers can get access to the renderer in a consistent state, and this might require support a raise_event which one could connect to and get the figure as soon as it is raised (which would be triggered on canvas creation for non gui backends presumably and after the window is raised for gui backends). In the callback, accessing canvas.renderer or canvas.get_renderer would return a renderer with proper sizing. JDH -- This SF.net email is sponsored by Sprint What will you do first with EVO, the first 4G phone? Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] tight subplot parameters
On Jul 22, 2010, at 8:59 AM, John Hunter wrote: On Thu, Jul 22, 2010 at 7:40 AM, Michiel de Hoon mjldeh...@yahoo.com wrote: Is a backend required to implement a get_renderer method? I only see it implemented in backend_agg.py, and it's missing in backend_bases.py, backend_template.py, backend_cairo.py, and in the macosx backend. If you want to try your code with the macosx backend, you can use fig.canvas.renderer instead of fig.canvas.get_renderer(). According to backend_bases.FigureCanvas, a renderer attr is not guaranteed either. The Agg* backends rely on get_renderer so that they can get a properly sized renderer on figure resizes, dpi changes, etc. We could handle this on the agg side with a property, or require all canvases to supply get renderer. The tricky bit is that renderers may not be available until draw time for some backends, and thus may not have proper size information if accessed too early (this is probably at the heart of the gtk bug we are seeing). It is probably a good idea to settle on something so developers can get access to the renderer in a consistent state, and this might require support a raise_event which one could connect to and get the figure as soon as it is raised (which would be triggered on canvas creation for non gui backends presumably and after the window is raised for gui backends). In the callback, accessing canvas.renderer or canvas.get_renderer would return a renderer with proper sizing. JDH Sorry, I don't know much about how the backends are structured. But this talk of backends got me thinking: Since the Agg backend (non-GUI version) is guaranteed to be installed (correct?), you could create an Agg renderer, and just use that to calculate all the sizing information. This experiment worked for all GUI backends on my system (Qt4Agg, TkAgg, MacOSX). Are there any downsides to using Agg to calculate sizing info and then rendering again on a GUI backend? Performance issues? I guess it's possible differences in sizing between backends will show up in the resized subplots, but these differences should be small, right? -Tony P.S. I've removed calls to subplots in example code for easier testing. import numpy as np import matplotlib.pyplot as plt from matplotlib.backends.backend_agg import RendererAgg from matplotlib.transforms import TransformedBbox, Affine2D PAD_INCHES = 0.1 def tight_layout(pad_inches=PAD_INCHES, h_pad_inches=None, w_pad_inches=None): Adjust subplot parameters to give specified padding. Parameters -- pad_inches : float minimum padding between the figure edge and the edges of subplots. h_pad_inches, w_pad_inches : float minimum padding (height/width) between edges of adjacent subplots. Defaults to `pad_inches`. if h_pad_inches is None: h_pad_inches = pad_inches if w_pad_inches is None: w_pad_inches = pad_inches fig = plt.gcf() renderer = RendererAgg(fig.get_figwidth(), fig.get_figheight(), fig.get_dpi()) tight_borders(fig, renderer, pad_inches=pad_inches) # NOTE: border padding affects subplot spacing; tighten border first tight_subplot_spacing(fig, renderer, h_pad_inches, w_pad_inches) def tight_borders(fig, renderer, pad_inches=PAD_INCHES): Stretch subplot boundaries to figure edges plus padding. # call draw to update the renderer and get accurate bboxes. fig.draw(renderer) bbox_original = fig.bbox_inches bbox_tight = fig.get_tightbbox(renderer).padded(pad_inches) # figure dimensions ordered like bbox.extents: x0, y0, x1, y1 lengths = np.array([bbox_original.width, bbox_original.height, bbox_original.width, bbox_original.height]) whitespace = (bbox_tight.extents - bbox_original.extents) / lengths # border padding ordered like bbox.extents: x0, y0, x1, y1 current_borders = np.array([fig.subplotpars.left, fig.subplotpars.bottom, fig.subplotpars.right, fig.subplotpars.top]) left, bottom, right, top = current_borders - whitespace fig.subplots_adjust(bottom=bottom, top=top, left=left, right=right) def tight_subplot_spacing(fig, renderer, h_pad_inches, w_pad_inches): Stretch subplots so adjacent subplots are separated by given padding. # Zero hspace and wspace to make it easier to calculate the spacing. fig.subplots_adjust(hspace=0, wspace=0) fig.draw(renderer) figbox = fig.bbox_inches ax_bottom, ax_top, ax_left, ax_right = _get_grid_boundaries(fig, renderer) nrows, ncols = ax_bottom.shape subplots_height = fig.subplotpars.top - fig.subplotpars.bottom if nrows 1: h_overlap_inches = ax_top[1:] - ax_bottom[:-1] hspace_inches = h_overlap_inches.max() + h_pad_inches hspace_fig_frac = hspace_inches / figbox.height hspace =
Re: [matplotlib-devel] tight subplot parameters
On Thu, Jul 22, 2010 at 8:57 AM, Tony S Yu tsyu80@ According to backend_bases.FigureCanvas, a renderer attr is not guaranteed either. The Agg* backends rely on get_renderer so that they can get a properly sized renderer on figure resizes, dpi changes, etc. We could handle this on the agg side with a property, or require all canvases to supply get renderer. No, this won't work because the sizing information depends on the GUI window size. Agg adapts the renderer to the GUI window size. So in GTKAgg we are using the Agg renderer, but GTK is determining the window size when it is raised. We try to get GTK to produce a canvas of a fixed size, but cannot guarantee it so we reset the renderer size in necessary when the canvas is raised. JDH -- This SF.net email is sponsored by Sprint What will you do first with EVO, the first 4G phone? Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] tight subplot parameters
--- On Thu, 7/22/10, John Hunter jdh2...@gmail.com wrote: We could handle this on the agg side with a property, or require all canvases to supply get renderer. Do we actually need a renderer in each of the backends? At least when I was writing the Mac OS X backend, it was not clear to me what functionality should go in the renderer and what should go in the graphics context. I expect that the same is true for the other postscript-style backends such as the cairo, pdf, and ps backends. In the end, I decided to mainly use the graphics context because it nicely maps to the Quartz graphics context at the C level, whereas the renderer doesn't have a corresponding data structure at the C level. In the Mac OS X backend, basically what the renderer does is to forward to the graphics context. In the ps backend most of the work is being done in the renderer instead of the graphics context, but again this is just a choice. I think that we should first remove such inconsistencies between backends. --Michiel -- This SF.net email is sponsored by Sprint What will you do first with EVO, the first 4G phone? Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] tight subplot parameters
On Jul 22, 2010, at 10:07 AM, John Hunter wrote: On Thu, Jul 22, 2010 at 8:57 AM, Tony S Yu tsyu80@ According to backend_bases.FigureCanvas, a renderer attr is not guaranteed either. The Agg* backends rely on get_renderer so that they can get a properly sized renderer on figure resizes, dpi changes, etc. We could handle this on the agg side with a property, or require all canvases to supply get renderer. No, this won't work because the sizing information depends on the GUI window size. Agg adapts the renderer to the GUI window size. So in GTKAgg we are using the Agg renderer, but GTK is determining the window size when it is raised. We try to get GTK to produce a canvas of a fixed size, but cannot guarantee it so we reset the renderer size in necessary when the canvas is raised. JDH I'm not sure if I understand. Are you talking about responding to window resizing events, or are you saying that Figure.get_height/get_width don't match the window size for some GUI backends? I create the Agg renderer based on Figure.get_height/get_width. If the window is resized, then the layout would definitely change, but you could call `tight_layout` again to adjust subplot spacing (which would create a new Agg renderer based on the new window size). Am I missing something here? Were you thinking I wanted to interactively adapt the spacings? (If that's the case, I wasn't that ambitious.) -Tony -- This SF.net email is sponsored by Sprint What will you do first with EVO, the first 4G phone? Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] tight subplot parameters
On Wed, Jul 21, 2010 at 10:09 PM, Tony S Yu tsy...@gmail.com wrote: Wow, I don't see that at all. I'm on OS X, mpl svn HEAD (r8567), and Qt4Agg. I don't have GTK installed, so unfortunately, I can't really do a proper comparison. Here's the output I get from your modified script. I get something similar with TkAgg (unfortunately, I get an AttributeError with the macosx backend). Works on my system for tkagg and qtagg4, so the bug appears gtkagg specific. Must be something in the draw vs window realized and sized pipeline. It appears you are getting some bogus size info.Wonder if connecting to the draw_event might help here (longshot) or if any any of Eric's recent work on show is impacting th behavior here. -- This SF.net email is sponsored by Sprint What will you do first with EVO, the first 4G phone? Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] tight subplot parameters
On Jul 21, 2010, at 11:26 PM, John Hunter wrote: On Wed, Jul 21, 2010 at 10:09 PM, Tony S Yu tsy...@gmail.com wrote: Wow, I don't see that at all. I'm on OS X, mpl svn HEAD (r8567), and Qt4Agg. I don't have GTK installed, so unfortunately, I can't really do a proper comparison. Here's the output I get from your modified script. I get something similar with TkAgg (unfortunately, I get an AttributeError with the macosx backend). Works on my system for tkagg and qtagg4, so the bug appears gtkagg specific. Must be something in the draw vs window realized and sized pipeline. It appears you are getting some bogus size info.Wonder if connecting to the draw_event might help here (longshot) or if any any of Eric's recent work on show is impacting th behavior here. Well, since I don't have access to GTK, it's not really something I can debug (kind of a cop out, I know). Your original GTK image is really strange: it seems as though the script moves the ticks, axis labels, and titles relative to their associated axes-frame. But the only function I use to affect the plot spacing is Figure.subplots_adjust (everything else in the script serves to calculate appropriate spacing-values). I don't think Figure.subplots_adjust is designed to move the ticks/axis-labels/titles relative to its own axes, right? -Tony -- This SF.net email is sponsored by Sprint What will you do first with EVO, the first 4G phone? Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel