quiver aspect ratio

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

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

···

jason-sage@...2130... 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?

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()

···

---------------------------------------------------------------------------
<type 'exceptions.ValueError'> 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:

<type 'exceptions.ValueError'>: 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

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

···

jason-sage@...2130... wrote:

In [10]: show()
---------------------------------------------------------------------------
<type 'exceptions.ValueError'> 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:

<type 'exceptions.ValueError'>: 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

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

···

jason-sage@...2130... wrote:

In [10]: show()
---------------------------------------------------------------------------
<type 'exceptions.ValueError'> 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:

<type 'exceptions.ValueError'>: 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