How doyou draw in pixel or lenght units?

I was afraid I'd have to do that. Do you have some

    > fairly simple sample code, that would help some.

What you want to do is use a line collection, see
http://matplotlib.sf.net/matplotlib.collections.py. You can specify a
list of line segments which can be in one coordinate system (eg
oriented lines with origin at 0 and lengths in points) and pass the
collection a list off offsets which can be in another coordinate
system (eg the locations of the lines in data coordinates). This is
just the kinds of thing that is useful for a vector field, where you
want oriented lines at x,y coords in data coords but lengths and
orientation of the lines in some physical coordinate system.

Here is a little example -- you'll also want to read up on mpl
transforms at http://matplotlib.sf.net/matplotlib.transforms.html

from matplotlib.transforms import scale_transform, Value
from matplotlib.collections import LineCollection
from pylab import figure, show
import matplotlib.numerix as nx

N = 100
angles = nx.mlab.rand(N)*2*nx.pi
radii = nx.mlab.rand(N)*144. # max line should be 2 inches long

segments = [((0,0), (r*nx.cos(theta), r*nx.sin(theta))) for r,theta in zip(radii, angles)]

offsets = zip(10*nx.mlab.rand(N),20*nx.mlab.randn(N))

fig = figure()
ax = fig.add_subplot(111)
coll = LineCollection(segments, offsets=offsets,
                      transOffset=ax.transData, # transforms the x,y offsets
                      )
# points/72.*dpi = pixels -- see matplotlib.transforms
trans = scale_transform(fig.dpi/Value(72.), fig.dpi/Value(72.))
coll.set_transform(trans) # the points to pixels transform

ax.add_collection(coll)
ax.set_xlim(0,10)
ax.set_ylim(0,20)
show()

John Hunter wrote:

What you want to do is use a line collection, see

John, you're fabulous, thanks. I think that's just what I was looking for. I figured that MPL would be designed in a way that this should be doable.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                         
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@...259...

Hi all,

I've written a little custom LineCollection class that draws a bunch of arrows pointing in given directions, with their origins at a set of (x,y) points. I use this type of plot to plot vector quantities varying over time, like an ocean current at a point, for instance. The x-axis is time, the y-axis is magnitude, and the arrow points in the direction.

I've enclosed a PNG of a sample plot (with clearly meaningless data), and the code that created it.

John Hunter wrote:

What you want to do is use a line collection,

Following John's sample code, I got it working, but I do have a few questions:

I'm now drawing the arrows as a LineCollection, and then drawing with 'o' markers on top to get the circles. Is there a way to add markers like that to the LineCollection, so that it's a single class?

The arrow heads look a bit off. If you make them much larger, they look fine, but small, they're not quire right. I suspect there is some rounding to integers that is going on. Or maybe it's something with the join style? (note, I'm using GTKAgg)

The way the code is written now, I need to pass in a axes object and a figure object, as I need the transData attribute from the axes and the dpi attribute from the figure. This creates a coupling that I'm not happy with. It's a bit odd that I have to pass the axes into the constructor, then add the LineCollection to the axes again. Is there a way to write this so that the transOffset and transform are applied when the LineCollection is added to the axes, rather than ahead of time?

Also, the Figure coupling is even worse -- is there a way to discover what figure an axes is on from the axes itself (or get it's dpi, which is all I really need?)

I guess what I'm hoping exists, and suggesting if it doesn't, is that the scaling and all would be "lazy", like lazy Values. The transform and scaling wouldn't be defined until it's time to actually render the LineCollection. I did something like that in my FloatCanvas. Each DrawObject has a _Draw method that gets a "WorldToPixel" function passed in. This function converts world coordinates that the object is defined in to pixel coordinates that it needs to draw itself with. That way, the object can exist entirely separate from a Canvas, and need know nothing about how it's coordinates need to be transformed until it needs to draw itself. Can something like this be done in MPL?

Would this be a useful plot type to add to MPL? If so, can you suggest an existing class that I should imitate to define what the interface would look like?

thanks,

-Chris

VectorPlot.png

VecPlot.py (2.49 KB)

···

--
Christopher Barker, Ph.D.
Oceanographer
                                         
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@...259...

Christopher Barker wrote:

Hi all,

I've written a little custom LineCollection class that draws a bunch of arrows pointing in given directions, with their origins at a set of (x,y) points. I use this type of plot to plot vector quantities varying over time, like an ocean current at a point, for instance. The x-axis is time, the y-axis is magnitude, and the arrow points in the direction.

the code behind this:

http://bayes.colorado.edu/cgi-bin/arrows/arrow_cgi.py

(just try the mock example with the data in the page) is coming to matplotlib in a week or two. I think it addresses some of the issues you're dealing with: it's an arrows-on-steroids class, with control over heads (including the half-heads shown) and more.

Cheers,

f

Fernando Perez wrote:

the code behind this:

http://bayes.colorado.edu/cgi-bin/arrows/arrow_cgi.py

(just try the mock example with the data in the page) is coming to matplotlib in a week or two.

Now you tell me!

Would you be willing to send me some code sooner? I don't want to work on my code more it you've already done a better job of it.

Did you make a "Collections" class. I can imagine that performance could be important sometimes.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                         
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@...259...

Christopher Barker wrote:

Fernando Perez wrote:

the code behind this:

http://bayes.colorado.edu/cgi-bin/arrows/arrow_cgi.py

(just try the mock example with the data in the page) is coming to matplotlib in a week or two.

Now you tell me!

Would you be willing to send me some code sooner? I don't want to work on my code more it you've already done a better job of it.

Did you make a "Collections" class. I can imagine that performance could be important sometimes.

I didn't write the code, so I can't send it. I'll contact the author and let him know.

Cheers,

f