Re: [matplotlib-devel] dpi-related positioning errors in Agg savefig
John, I made some more changes in quiver, and I think they will ensure that dpi changes are handled correctly as far as arrows are concerned, both in the plot and in the key. There is still a problem with the key label, and it can be seen clearly in the attached slight modification of quiver_demo.py. There are actually two visible problems: 1) The hline generated by frac is too long with dpi=50. 2) The positioning and sizing of the key bbox are also dpi-dependent, as I verified by using your bbox-display trick. I went hunting through text.py, mathtext.py, backend_bases, and backend_agg without figuring out where the problem is. The right dpi seems to be getting used at mathtext parsing time. Maybe it is not actually getting propagated all the way into the code that gets the font metrics. I did not try to trace it that far. Along the way, I found that in backend_bases, print_figure was doing what appears to be a completely unnecessary draw operation after restoring the original dpi, so I commented that out. This speeds up backend_driver.py agg by a few percent. Eric John Hunter wrote: On Sat, Apr 26, 2008 at 2:04 PM, Eric Firing <[EMAIL PROTECTED]> wrote: The attached script, run on svn mpl, illustrates a positioning problem: note that the subplot titles are badly positioned in the 50 dpi version. I believe that changing from 150 to 50 dpi should yield a perfect scaling of everything in the plot, but it doesn't. There is a similar problem with a quiver key positioned outside the axes frame, but I don't have a trivial example yet; I am hoping that whatever solves the title positioning problem will take care of that also. If not, I will make a simple example and we can attack it separately. There were two problems with title positioning. The first was that the title offset transformation was hardcoded in pixels and not dpi, and the second was that is was not getting notifed when the figure dpi was changed. I changed the offset to read: self.titleOffsetTrans = mtransforms.Affine2D().translate( 0.0, 5.0*self.figure.dpi/72.) and added a callbacks registry to the figure instance so that observers could be notified when dpi was changed (dpi used to be a lazy value on the maintenance branch but is a plain-ol-value on the trunk). def on_dpi_change(fig): self.titleOffsetTrans.clear().translate( 0.0, 5.0*fig.dpi/72.) self.figure.callbacks.connect('dpi_changed', on_dpi_change) It looks like the problem in the quiver code is that the "labelsep" property reads the dpi when the QuiverKey is intiitalized but does not get notified on dpi change. I added a callback there too so you should test to see if this helps. The dpi setting is also referenced in the _set_transform method. Since you are more familiar with the quiver code that I am, and this hint may point you in the right direction, I'll let you take a look at that and see if a callback is needed. On a related note, one trick I use when debugging text layout problems is to turn on the "bbox". If the bbox is right but the text is in the wrong place, you know it is in the layout. If the bbox is in the wrong place, you know the problem is in the font metrics: boxprops = dict(facecolor='red') ax1.set_title('Top Plot', bbox=boxprops) JDH ''' Demonstration of quiver and quiverkey functions. This is using the new version coming from the code in quiver.py. Known problem: the plot autoscaling does not take into account the arrows, so those on the boundaries are often out of the picture. This is *not* an easy problem to solve in a perfectly general way. The workaround is to manually expand the axes. ''' import sys import matplotlib matplotlib.use('agg') from pylab import * X,Y = meshgrid( arange(0,2*pi,.2),arange(0,2*pi,.2) ) U = cos(X) V = sin(Y) #1 figure() Q = quiver( U, V) qk = quiverkey(Q, 0.5, 0.92, 2, r'$2 \frac{m}{s}$', labelpos='W', fontproperties={'weight': 'bold'}) l,r,b,t = axis() dx, dy = r-l, t-b axis([l-0.05*dx, r+0.05*dx, b-0.05*dy, t+0.05*dy]) title('Minimal arguments, no kwargs') savefig('q1_050.png', dpi=50) savefig('q1_150.png', dpi=150) #2 figure() Q = quiver( X, Y, U, V, units='width') qk = quiverkey(Q, 0.9, 0.95, 2, r'$2 \frac{m}{s}$', labelpos='E', coordinates='figure', fontproperties={'weight': 'bold'}) axis([-1, 7, -1, 7]) title('scales with plot width, not view') savefig('q2_050.png', dpi=50) savefig('q2_150.png', dpi=150) #3 figure() Q = quiver( X[::3, ::3], Y[::3, ::3], U[::3, ::3], V[::3, ::3], pivot='mid', color='r', units='inches' ) qk = quiverkey(Q, 0.5, 0.03, 1, r'$1 \frac{m}{s}$', fontproperties={'weight': 'bold'}) plot( X[::3, ::3], Y[::3, ::3], 'k.') axis([-1, 7, -1, 7]) title("pivot='mid'; every third arrow; units='inches'") savefig('q3_050.png', dpi=50) savefig('q3_150.png', dpi=150) #4 figure() M = sqrt(pow(U, 2) + pow(V, 2)) Q = quiver( X, Y, U, V, M,
Re: [matplotlib-devel] dpi-related positioning errors in Agg savefig
Eric Firing wrote: John, I made some more changes in quiver, and I think they will ensure that dpi changes are handled correctly as far as arrows are concerned, both in the plot and in the key. There is still a problem with the key label, and it can be seen clearly in the attached slight modification of quiver_demo.py. There are actually two visible problems: 1) The hline generated by frac is too long with dpi=50. 2) The positioning and sizing of the key bbox are also dpi-dependent, as I verified by using your bbox-display trick. The plot thickens. The postscript backend is completely confused by the quiver plot. Try the attached example. pdf seems OK. Eric import sys import matplotlib matplotlib.use('ps') from pylab import * X,Y = meshgrid( arange(0,2*pi,.2),arange(0,2*pi,.2) ) U = cos(X) V = sin(Y) #1 figure() Q = quiver( U, V) qk = quiverkey(Q, 0.5, 0.92, 2, r'$2 \frac{m}{s}$', labelpos='W', fontproperties={'weight': 'bold'}) l,r,b,t = axis() dx, dy = r-l, t-b axis([l-0.05*dx, r+0.05*dx, b-0.05*dy, t+0.05*dy]) title('Minimal arguments, no kwargs') savefig('q1_defdpi.eps') savefig('q1_050.eps', dpi=50) savefig('q1_150.eps', dpi=150) savefig('q1_072.eps', dpi=72) - This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] dpi-related positioning errors in Agg savefig
On Sun, Apr 27, 2008 at 3:14 AM, Eric Firing <[EMAIL PROTECTED]> wrote: > 1) The hline generated by frac is too long with dpi=50. The problem with the hline appears to be that the width of the line in the frac has a component that depends on the thickness thickness = state.font_output.get_underline_thickness( state.font, state.fontsize, state.dpi) width = max(num.width, den.width) + thickness * 10. and get_underline_thickness here is defaulting to 1.0 because of this max call in get_underline_thickness return max(1.0, cached_font.font.underline_thickness / 64.0 / fontsize * 10.0) Michael -- what is the role of these 10.0 scale factors, which is showing up in both the frac call and the get_underline_thickness? Is this something from Knuth, or is it a fudge factor that gets it mostly right? I suspect we will need something like width = max(num.width, den.width) + thickness * 10. * state.dpi/72. but with this change the frac bar looks a little too wide -- which is why I'm wondering if there is something magic about 10. or if another number might serve better. > Along the way, I found that in backend_bases, print_figure was doing what > appears to be a completely unnecessary draw operation after restoring the > original dpi, so I commented that out. This speeds up backend_driver.py agg > by a few percent. I think you are right here -- because we are creating a new FigureCanvas and hence a new renderer in the switch_backend call we do not need to redraw the original figure with the original facecolor, edgecolor and dpi params. In older versions of mpl, if memory serves correctly, calling savefig would reuse the same renderer so after the print to hardcopy we would redraw so the figure in the GUI window would look right. But I agree this looks superfluous in light of the current code which is creating a new canvas with each savefig. JDH - This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] dpi-related positioning errors in Agg savefig
On Sun, Apr 27, 2008 at 12:56 PM, Eric Firing <[EMAIL PROTECTED]> wrote: > The plot thickens. The postscript backend is completely confused by the > quiver plot. Try the attached example. Argg, that was a subtle one -- there was a bug in backend ps which was exposed only if you are using a path collection with offsets, transoffset and clippath and cliprect both None. In that scenario, the translate in the bind def function was not getting wrapped in a gsave/grestore pair, which was causing the axes to be drawn in the wrong place because the translate from the offset remained in effect. I tried following the draw_markers logic and putting the gsave/grestore in the ps_cmd, eg in draw_markers Michael writes ijn a comment: ps_cmd = ['/o {', 'gsave', 'newpath', 'translate'] # dont want the translate to be global so clearly he was bumping up against the same problem with markers. For some reason, trying the same thing in the path_collection was not working for me, so I resorted to the somewhat hackish approach of forcing _draw_ps to wrap a gsave/grestore if it wasn't getting one from the cliprect or clippath: needwrap = not (clippath or cliprect) if needwrap: # we need to make sure that there is at least 1 # save/grestore around each ps write so we'll force it if # we're not getting one from the cliprecot or clippath. # hackish, yes write('gsave\n') and then if needwrap: write('grestore\n') I think there will be cleaner way, but it will need some fresh eyeballs tomorrow and this will provide a temporary fix. JDH - This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] dpi-related positioning errors in Agg savefig
On Sun, Apr 27, 2008 at 8:28 PM, John Hunter <[EMAIL PROTECTED]> wrote: > Argg, that was a subtle one -- there was a bug in backend ps which was > exposed only if you are using a path collection with offsets, > transoffset and clippath and cliprect both None. In that scenario, > the translate in the bind def function was not getting wrapped in a One thing I failed to make clear: the artist with said properties is quiver.QuiverKey.vector JDH - This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
Re: [matplotlib-devel] dpi-related positioning errors in Agg savefig
John Hunter wrote: > On Sun, Apr 27, 2008 at 12:56 PM, Eric Firing <[EMAIL PROTECTED]> wrote: > >> The plot thickens. The postscript backend is completely confused by the >> quiver plot. Try the attached example. > > > Argg, that was a subtle one -- there was a bug in backend ps which was > exposed only if you are using a path collection with offsets, > transoffset and clippath and cliprect both None. In that scenario, > the translate in the bind def function was not getting wrapped in a > gsave/grestore pair, which was causing the axes to be drawn in the > wrong place because the translate from the offset remained in effect. > I tried following the draw_markers logic and putting the > gsave/grestore in the ps_cmd, eg in draw_markers Michael writes ijn a > comment: > > ps_cmd = ['/o {', 'gsave', 'newpath', 'translate'] # dont want > the translate to be global > > so clearly he was bumping up against the same problem with markers. > For some reason, trying the same thing in the path_collection was not > working for me, so I resorted to the somewhat hackish approach of > forcing _draw_ps to wrap a gsave/grestore if it wasn't getting one > from the cliprect or clippath: > > needwrap = not (clippath or cliprect) > if needwrap: > # we need to make sure that there is at least 1 > # save/grestore around each ps write so we'll force it if > # we're not getting one from the cliprecot or clippath. > # hackish, yes > write('gsave\n') > > and then > > if needwrap: > write('grestore\n') > > I think there will be cleaner way, but it will need some fresh > eyeballs tomorrow and this will provide a temporary fix. I went ahead and committed an alternative fix that I think is cleaner, and greatly reduces the number of needless gsave/grestore pairs. Your version of the method is still there, with a mangled name, for easy reference and testing until we are sure which way to go. Sorry for whatever duplicated effort there has been. I did not intend to spend a fair chunk of the day working on this, but I let myself get sucked in. It was a challenge. As mentioned in a message a few minutes ago that I don't think went to the list, my gs interpreter is choking on the apostrophe (single quote) character, as in title or label strings. I can't find any reason why this should cause trouble--maybe it is a particular version or configuration of gs. Eric - This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone ___ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel