[Matplotlib-users] quiver aspect ratio From: - 2008-09-17 21:54:55 ```Recently I noticed that the quiver plots all make the arrows as if the plot had aspect ratio 1. See, for example, the documentation for quiver: In all cases the arrow aspect ratio is 1, so that if *U*==*V* the angle of the arrow on the plot is 45 degrees CCW from the *x*-axis. This seems to make the plot pretty useless if the aspect ratio is not 1, since then the slopes of the arrows do not match up with the coordinate axes. What is the reason for this design decision? Does it have to do with the arrows distorting if the aspect ratio is not 1? At one time, there was talk of adding a line version of quiver (as opposed to the patch version there now). See http://article.gmane.org/gmane.comp.python.matplotlib.devel/1885. Has that happened? I suppose a line version would allow different aspect ratios. Is there an easy way to get a correct quiver plot (i.e., correct slopes) now if the aspect ratio is not 1? Thanks, Jason ```
 Re: [Matplotlib-users] quiver aspect ratio From: Eric Firing - 2008-09-18 00:36:26 ```jason-sage@... wrote: > Recently I noticed that the quiver plots all make the arrows as if the > plot had aspect ratio 1. See, for example, the documentation for quiver: > > In all cases the arrow aspect ratio is 1, so that if *U*==*V* the > angle of the arrow on the plot is 45 degrees CCW from the *x*-axis. > > > This seems to make the plot pretty useless if the aspect ratio is not 1, > since then the slopes of the arrows do not match up with the coordinate > axes. What is the reason for this design decision? Does it have to do > with the arrows distorting if the aspect ratio is not 1? At one time, No, the design suits my applications: I want to plot arrows indicating ocean current vectors as a function of position in the horizontal, or as a function of depth and time. But I don't think the design is limiting. See below. > there was talk of adding a line version of quiver (as opposed to the > patch version there now). See > http://article.gmane.org/gmane.comp.python.matplotlib.devel/1885. Has > that happened? I suppose a line version would allow different aspect > ratios. No, in this respect it would be no different. And no, a line version has not been added. > > Is there an easy way to get a correct quiver plot (i.e., correct slopes) > now if the aspect ratio is not 1? Please provide a script that illustrates what you think is the problem. Exactly what is it that you want to do, and don't know how to do with quiver as it is? Note that you have full control over U and V; you can make the arrows point any direction you want, and be any length you want. And you can locate them anywhere you want. Basemap illustrates how quiver can be used with curvilinear coordinates; the U and V are adjusted to align the arrows with the coordinates. It is possible that quiver needs more modification to work properly and flexibly with the new transforms implementation; in fact I know of a bug that this introduced, and I will commit a correction shortly. I have not looked into quiver behavior with transforms-based projections. They might indeed call for a design change. Eric ```
 Re: [Matplotlib-users] quiver aspect ratio From: - 2008-09-18 09:23:53 ```First off, in rereading my message, it sounded more abrasive than I intended. I should have asked more questions and complained less; sorry. Eric Firing wrote: > jason-sage@... wrote: > >> >> Is there an easy way to get a correct quiver plot (i.e., correct >> slopes) now if the aspect ratio is not 1? > > Please provide a script that illustrates what you think is the > problem. Exactly what is it that you want to do, and don't know how > to do with quiver as it is? One application I'd like to use it for is direction field plots for first order linear differential equations (i.e., y' = some function of x and y). Given the function y'(x,y), I plot a quiver where U is a vector of ones and V is a vector of y'(corresponding x and y coordinates), so for the arrow based at point (x,y), the arrow has slope corresponding to the slope of the solution that passes through (x,y). However, when the aspect ratio is not one, a solution will have a different slope (because the slope is measured in coordinates corresponding to the axes) than the slope of the arrow. Here is a small example, modified from the quiver examples in matplotlib. from pylab import * X,Y = meshgrid( arange(0,1,.2),arange(0,1,.2) ) def yprime(x,y): return 1 U,V = meshgrid([1]*len(X), [1]*len(Y)) figure() Q = quiver(X,Y,U, V) # This is a solution to the differential equation y'=1, but it doesn't # look like it because the slopes do not respect the aspect ratio of # the plot. What should happen is the arrows should point along the # line. plot([0,1],[0,1]) axis([0,1,0,0.5]) title("Slope Field for \$dy/dx=1\$") show() In looking at the basemap examples (specifically quiver_demo.py), it looks like you specifically rotate the vectors to match up with map coordinates; is that right? Applying to the situation above, do I need to rotate my vectors to respect the aspect ratio? What's the easiest way to get quiver(X,Y,U,V) to behave so that the vectors plotted would, for each coordinate (x,y) and corresponding (u,v), be parallel to the vector between (x,y) and (x+u, y+v) (where (x, y) and (u,v) are taken as coordinates in the axis coordinate system). Please let me know if I'm not clear in what I'm asking. Thanks, Jason > > Note that you have full control over U and V; you can make the arrows > point any direction you want, and be any length you want. And you can > locate them anywhere you want. > > Basemap illustrates how quiver can be used with curvilinear > coordinates; the U and V are adjusted to align the arrows with the > coordinates. > > It is possible that quiver needs more modification to work properly > and flexibly with the new transforms implementation; in fact I know of > a bug that this introduced, and I will commit a correction shortly. > I have not looked into quiver behavior with transforms-based > projections. They might indeed call for a design change. > > Eric > > ```
 Re: [Matplotlib-users] quiver aspect ratio From: - 2008-09-18 15:07:08 ```Eric Firing wrote: > Jason, > >> >> In looking at the basemap examples (specifically quiver_demo.py), it >> looks like you specifically rotate the vectors to match up with map >> coordinates; is that right? Applying to the situation above, do I need > Yes. >> to rotate my vectors to respect the aspect ratio? What's the easiest >> way to get quiver(X,Y,U,V) to behave so that the vectors plotted >> would, for each coordinate (x,y) and corresponding (u,v), be parallel >> to the vector between (x,y) and (x+u, y+v) (where (x, y) and (u,v) >> are taken as coordinates in the axis coordinate system). > > Well, the easiest way is to build mpl from svn; a few minutes ago I > added this capability to quiver, selectable with an "angles" kwarg. Thanks! I'm working with matplotlib in Sage, so I'll probably update the matplotlib package in Sage if it is fairly stable. Do you know when the next release of matplotlib will be, in case it isn't stable for me? P.S. Sorry for the duplicate messages to you, Eric. I keep hitting reply instead of reply-all. Jason ```
 Re: [Matplotlib-users] quiver aspect ratio From: Eric Firing - 2008-09-18 15:39:04 ```jason-sage@... wrote: > Eric Firing wrote: >> Jason, >> >>> In looking at the basemap examples (specifically quiver_demo.py), it >>> looks like you specifically rotate the vectors to match up with map >>> coordinates; is that right? Applying to the situation above, do I need >> Yes. >>> to rotate my vectors to respect the aspect ratio? What's the easiest >>> way to get quiver(X,Y,U,V) to behave so that the vectors plotted >>> would, for each coordinate (x,y) and corresponding (u,v), be parallel >>> to the vector between (x,y) and (x+u, y+v) (where (x, y) and (u,v) >>> are taken as coordinates in the axis coordinate system). >> Well, the easiest way is to build mpl from svn; a few minutes ago I >> added this capability to quiver, selectable with an "angles" kwarg. > > Thanks! > > I'm working with matplotlib in Sage, so I'll probably update the > matplotlib package in Sage if it is fairly stable. Do you know when the > next release of matplotlib will be, in case it isn't stable for me? No, as far as I know there is no release schedule. The last one, 0.98.3, was not very long ago--early August--so I would not expect another until a couple more months have elapsed. But I could be wrong about that. Eric ```
 Re: [Matplotlib-users] quiver aspect ratio From: - 2008-09-20 03:26:02 ```Eric Firing wrote: >>> Well, the easiest way is to build mpl from svn; a few minutes ago I >>> added this capability to quiver, selectable with an "angles" kwarg. Eric, I tried just copying the quiver.py SVN version 6114 into my existing matplotlib install and numpy 1.1.1. When running my example posted earlier with the angles='xy' keyword added to the quiver call, I get the following error: In [10]: show() --------------------------------------------------------------------------- Traceback (most recent call last) /usr/lib/python2.5/site-packages/matplotlib/backends/backend_gtk.py in expose_event(self, widget, event) 331 x, y, w, h = self.allocation 332 self._pixmap_prepare (w, h) --> 333 self._render_figure(self._pixmap, w, h) 334 self._need_redraw = False 335 /usr/lib/python2.5/site-packages/matplotlib/backends/backend_gtkagg.py in _render_figure(self, pixmap, width, height) 73 def _render_figure(self, pixmap, width, height): 74 if DEBUG: print 'FigureCanvasGTKAgg.render_figure' ---> 75 FigureCanvasAgg.draw(self) 76 if DEBUG: print 'FigureCanvasGTKAgg.render_figure pixmap', pixmap 77 #agg_to_gtk_drawable(pixmap, self.renderer._renderer, None) /usr/lib/python2.5/site-packages/matplotlib/backends/backend_agg.py in draw(self) 259 260 self.renderer = self.get_renderer() --> 261 self.figure.draw(self.renderer) 262 263 def get_renderer(self): /usr/lib/python2.5/site-packages/matplotlib/figure.py in draw(self, renderer) 757 758 # render the axes --> 759 for a in self.axes: a.draw(renderer) 760 761 # render the figure text /usr/lib/python2.5/site-packages/matplotlib/axes.py in draw(self, renderer, inframe) 1521 1522 for zorder, i, a in dsu: -> 1523 a.draw(renderer) 1524 1525 renderer.close_group('axes') /usr/lib/python2.5/site-packages/matplotlib/quiver.py in draw(self, renderer) 423 self._init() 424 if self._new_UV or self.angles == 'xy': --> 425 verts = self._make_verts(self.U, self.V) 426 self.set_verts(verts, closed=False) 427 self._new_UV = False /usr/lib/python2.5/site-packages/matplotlib/quiver.py in _make_verts(self, U, V) 483 else: 484 theta = ma.asarray(self.angles*np.pi/180.0).filled(0) --> 485 xy = (X+Y*1j) * np.exp(1j*theta)*self.width 486 xy = xy[:,:,np.newaxis] 487 XY = ma.concatenate((xy.real, xy.imag), axis=2) /usr/lib/python2.5/site-packages/numpy/ma/core.py in __mul__(self, other) 1710 def __mul__(self, other): 1711 "Multiply other by self, and return a new masked array." -> 1712 return multiply(self, other) 1713 # 1714 def __div__(self, other): /usr/lib/python2.5/site-packages/numpy/ma/core.py in __call__(self, a, b, *args, **kwargs) 513 m = mask_or(getmask(a), getmask(b)) 514 (d1, d2) = (get_data(a), get_data(b)) --> 515 result = self.f(d1, d2, *args, **kwargs).view(get_masked_subclass(a, b)) 516 if result.size > 1: 517 if m is not nomask: : shape mismatch: objects cannot be broadcast to a single shape Do you know if this is caused by trying to use the new quiver.py in 0.98.3? Does my example before (copied below for convenience) work for you? from pylab import * X,Y = meshgrid( arange(0,1,.2),arange(0,1,.2) ) def yprime(x,y): return 1 U,V = meshgrid([1]*len(X), [1]*len(Y)) figure() Q = quiver(X,Y,U, V, angles='xy') # This is a solution to the differential equation y'=1, but it doesn't # look like it because the slopes do not respect the aspect ratio of # the plot. What should happen is the arrows should point along the # line. plot([0,1],[0,1]) axis([0,1,0,0.5]) title("Slope Field for \$dy/dx=1\$") show() Thanks, Jason ```
 Re: [Matplotlib-users] quiver aspect ratio From: Eric Firing - 2008-09-20 03:24:46 ```jason-sage@... wrote: > Eric Firing wrote: >>>> Well, the easiest way is to build mpl from svn; a few minutes ago I >>>> added this capability to quiver, selectable with an "angles" kwarg. > > Eric, > > I tried just copying the quiver.py SVN version 6114 into my existing > matplotlib install and numpy 1.1.1. When running my example posted > earlier with the angles='xy' keyword added to the quiver call, I get the > following error: Fixed in svn 6115. Sorry I didn't catch it initially. It was a pretty basic bug. Eric > > In [10]: show() > --------------------------------------------------------------------------- > Traceback (most recent call last) > > /usr/lib/python2.5/site-packages/matplotlib/backends/backend_gtk.py in > expose_event(self, widget, event) > 331 x, y, w, h = self.allocation > 332 self._pixmap_prepare (w, h) > --> 333 self._render_figure(self._pixmap, w, h) > 334 self._need_redraw = False > 335 > > /usr/lib/python2.5/site-packages/matplotlib/backends/backend_gtkagg.py > in _render_figure(self, pixmap, width, height) > 73 def _render_figure(self, pixmap, width, height): > 74 if DEBUG: print 'FigureCanvasGTKAgg.render_figure' > ---> 75 FigureCanvasAgg.draw(self) > 76 if DEBUG: print 'FigureCanvasGTKAgg.render_figure > pixmap', pixmap > 77 #agg_to_gtk_drawable(pixmap, self.renderer._renderer, None) > > /usr/lib/python2.5/site-packages/matplotlib/backends/backend_agg.py in > draw(self) > 259 > 260 self.renderer = self.get_renderer() > --> 261 self.figure.draw(self.renderer) > 262 > 263 def get_renderer(self): > > /usr/lib/python2.5/site-packages/matplotlib/figure.py in draw(self, > renderer) > 757 > 758 # render the axes > --> 759 for a in self.axes: a.draw(renderer) > 760 > 761 # render the figure text > > /usr/lib/python2.5/site-packages/matplotlib/axes.py in draw(self, > renderer, inframe) > 1521 > 1522 for zorder, i, a in dsu: > -> 1523 a.draw(renderer) > 1524 > 1525 renderer.close_group('axes') > > /usr/lib/python2.5/site-packages/matplotlib/quiver.py in draw(self, > renderer) > 423 self._init() > 424 if self._new_UV or self.angles == 'xy': > --> 425 verts = self._make_verts(self.U, self.V) > 426 self.set_verts(verts, closed=False) > 427 self._new_UV = False > > /usr/lib/python2.5/site-packages/matplotlib/quiver.py in > _make_verts(self, U, V) > 483 else: > 484 theta = ma.asarray(self.angles*np.pi/180.0).filled(0) > --> 485 xy = (X+Y*1j) * np.exp(1j*theta)*self.width > 486 xy = xy[:,:,np.newaxis] > 487 XY = ma.concatenate((xy.real, xy.imag), axis=2) > > /usr/lib/python2.5/site-packages/numpy/ma/core.py in __mul__(self, other) > 1710 def __mul__(self, other): > 1711 "Multiply other by self, and return a new masked array." > -> 1712 return multiply(self, other) > 1713 # > 1714 def __div__(self, other): > > /usr/lib/python2.5/site-packages/numpy/ma/core.py in __call__(self, a, > b, *args, **kwargs) > 513 m = mask_or(getmask(a), getmask(b)) > 514 (d1, d2) = (get_data(a), get_data(b)) > --> 515 result = self.f(d1, d2, *args, > **kwargs).view(get_masked_subclass(a, b)) > 516 if result.size > 1: > 517 if m is not nomask: > > : shape mismatch: objects cannot be > broadcast to a single shape > > > > Do you know if this is caused by trying to use the new quiver.py in > 0.98.3? Does my example before (copied below for convenience) work for > you? > > from pylab import * > > X,Y = meshgrid( arange(0,1,.2),arange(0,1,.2) ) > def yprime(x,y): > return 1 > > U,V = meshgrid([1]*len(X), [1]*len(Y)) > > figure() > Q = quiver(X,Y,U, V, angles='xy') > > # This is a solution to the differential equation y'=1, but it doesn't > # look like it because the slopes do not respect the aspect ratio of > # the plot. What should happen is the arrows should point along the > # line. > plot([0,1],[0,1]) > > axis([0,1,0,0.5]) > > title("Slope Field for \$dy/dx=1\$") > show() > > > Thanks, > > Jason > ```
 Re: [Matplotlib-users] quiver aspect ratio From: Eric Firing - 2008-09-20 04:08:50 ```jason-sage@... wrote: > Eric Firing wrote: >>>> Well, the easiest way is to build mpl from svn; a few minutes ago I >>>> added this capability to quiver, selectable with an "angles" kwarg. > > Eric, > > I tried just copying the quiver.py SVN version 6114 into my existing > matplotlib install and numpy 1.1.1. When running my example posted > earlier with the angles='xy' keyword added to the quiver call, I get the > following error: So do I. I'll have to track down the bug. Eric > > In [10]: show() > --------------------------------------------------------------------------- > Traceback (most recent call last) > > /usr/lib/python2.5/site-packages/matplotlib/backends/backend_gtk.py in > expose_event(self, widget, event) > 331 x, y, w, h = self.allocation > 332 self._pixmap_prepare (w, h) > --> 333 self._render_figure(self._pixmap, w, h) > 334 self._need_redraw = False > 335 > > /usr/lib/python2.5/site-packages/matplotlib/backends/backend_gtkagg.py > in _render_figure(self, pixmap, width, height) > 73 def _render_figure(self, pixmap, width, height): > 74 if DEBUG: print 'FigureCanvasGTKAgg.render_figure' > ---> 75 FigureCanvasAgg.draw(self) > 76 if DEBUG: print 'FigureCanvasGTKAgg.render_figure > pixmap', pixmap > 77 #agg_to_gtk_drawable(pixmap, self.renderer._renderer, None) > > /usr/lib/python2.5/site-packages/matplotlib/backends/backend_agg.py in > draw(self) > 259 > 260 self.renderer = self.get_renderer() > --> 261 self.figure.draw(self.renderer) > 262 > 263 def get_renderer(self): > > /usr/lib/python2.5/site-packages/matplotlib/figure.py in draw(self, > renderer) > 757 > 758 # render the axes > --> 759 for a in self.axes: a.draw(renderer) > 760 > 761 # render the figure text > > /usr/lib/python2.5/site-packages/matplotlib/axes.py in draw(self, > renderer, inframe) > 1521 > 1522 for zorder, i, a in dsu: > -> 1523 a.draw(renderer) > 1524 > 1525 renderer.close_group('axes') > > /usr/lib/python2.5/site-packages/matplotlib/quiver.py in draw(self, > renderer) > 423 self._init() > 424 if self._new_UV or self.angles == 'xy': > --> 425 verts = self._make_verts(self.U, self.V) > 426 self.set_verts(verts, closed=False) > 427 self._new_UV = False > > /usr/lib/python2.5/site-packages/matplotlib/quiver.py in > _make_verts(self, U, V) > 483 else: > 484 theta = ma.asarray(self.angles*np.pi/180.0).filled(0) > --> 485 xy = (X+Y*1j) * np.exp(1j*theta)*self.width > 486 xy = xy[:,:,np.newaxis] > 487 XY = ma.concatenate((xy.real, xy.imag), axis=2) > > /usr/lib/python2.5/site-packages/numpy/ma/core.py in __mul__(self, other) > 1710 def __mul__(self, other): > 1711 "Multiply other by self, and return a new masked array." > -> 1712 return multiply(self, other) > 1713 # > 1714 def __div__(self, other): > > /usr/lib/python2.5/site-packages/numpy/ma/core.py in __call__(self, a, > b, *args, **kwargs) > 513 m = mask_or(getmask(a), getmask(b)) > 514 (d1, d2) = (get_data(a), get_data(b)) > --> 515 result = self.f(d1, d2, *args, > **kwargs).view(get_masked_subclass(a, b)) > 516 if result.size > 1: > 517 if m is not nomask: > > : shape mismatch: objects cannot be > broadcast to a single shape > > > > Do you know if this is caused by trying to use the new quiver.py in > 0.98.3? Does my example before (copied below for convenience) work for > you? > > from pylab import * > > X,Y = meshgrid( arange(0,1,.2),arange(0,1,.2) ) > def yprime(x,y): > return 1 > > U,V = meshgrid([1]*len(X), [1]*len(Y)) > > figure() > Q = quiver(X,Y,U, V, angles='xy') > > # This is a solution to the differential equation y'=1, but it doesn't > # look like it because the slopes do not respect the aspect ratio of > # the plot. What should happen is the arrows should point along the > # line. > plot([0,1],[0,1]) > > axis([0,1,0,0.5]) > > title("Slope Field for \$dy/dx=1\$") > show() > > > Thanks, > > Jason > ```