Ticket #2922 (new enhancement)
scale function for plot_vector_field
| Reported by: | schilly | Owned by: | was |
|---|---|---|---|
| Priority: | minor | Milestone: | sage-5.10 |
| Component: | graphics | Keywords: | |
| Cc: | jason, novoselt | Work issues: | |
| Report Upstream: | N/A | Reviewers: | |
| Authors: | Merged in: | ||
| Dependencies: | Stopgaps: |
Description
When plotting a vector field, it is useful to be able to scale the length of the arrows. This is similar to mma:ScaleFunction.
e.g.:
- an upper therehold: lambda x: min(1,x)
- logarithmic: lambda x: log(1+x)
where x is the positive absolute length of the vector and each coordinate is divided by that - or some generalization of that.
Change History
comment:2 Changed 4 years ago by jason
So basically you want to give a function that gives the length of a vector? That sounds reasonable.
Since Sage is actually the thing that generates the vectors, and matplotlib just plots them, I think scaling the vectors in Sage to each have the length you want is the correct thing to do here, before passing them to matplotlib.
plot_vector_field((-y,-x), (x,0,1),(y,0,1), norm=f)
where f is a function defined to take f(v,w), where v is the vector, w is the point in space (as a vector).
so your examples would be:
f=lambda v,w: min(1,v.norm())
f=lambda v,w: log(1+v.norm())
We could then adjust the scale parameter of the quiver plot so that the arrows would plot exactly the length you wanted (I believe units='x', scale=1 should do the job).
comment:3 Changed 4 years ago by kcrisman
Well, yeah, you can use the same thing you do in plot_slope_field to get the norm (in fact, numpy has this nice absolute() function that mpl uses). But it looked to me like it might not be possible to get around the auto-scaling that mpl does (see matplotlib.quiver??), since ordinarily scale=1 is definitely not what one wants. I will look to see if units='x' would actually get around that.
comment:4 Changed 4 years ago by jason
The scale argument says the ratio of length to units, where units are specified in the units parameter. Usually the units are not in terms of data coordinates, I believe. So what you want is to make the units equal to data coordinates (i.e., 'x' or 'y'), instead of a function of the plot size, like 'width' and 'height' are.
comment:5 Changed 4 years ago by jason
After playing with this a bit more, I decided that, while what matplotlib has makes sense, it isn't what we want. I just sent a message to the matplotlib-users mailing list.
comment:6 Changed 4 years ago by jason
Eric Firing just committed the change to the matplotlib quiver function that allows us to scale arrows easily. See http://www.nabble.com/scaling-arrows-in-quiver-tt25673613.html#a25673613
Now we just need to update the matplotlib spkg and wrap it (the new scale_units function). This might wait a while until the next release of matplotlib comes out, unless someone wants to update the spkg before then.
comment:7 Changed 4 years ago by jason
(his commit is here: http://github.com/astraw/matplotlib/commit/b24fa7c6aef0db82ae4c9108c86abf3ddd871e34 )
comment:8 follow-up: ↓ 9 Changed 4 years ago by edrex
I'd like to be able to pass the scale kwarg to quiver, is that what we're talking about doing?
comment:9 in reply to: ↑ 8 Changed 4 years ago by jason
Replying to edrex:
I'd like to be able to pass the scale kwarg to quiver, is that what we're talking about doing?
yes.
comment:10 follow-up: ↓ 11 Changed 2 years ago by kcrisman
- Report Upstream set to N/A
See also #11208, which is also about quivers.
Is this ready to wrap? We've definitely updated mpl since a year and a half ago.
comment:11 in reply to: ↑ 10 Changed 2 years ago by jason
Replying to kcrisman:
Is this ready to wrap? We've definitely updated mpl since a year and a half ago.
Yes, it should be ready to wrap now.
comment:13 Changed 8 months ago by benjaminfjones
Just a note, this ticket would provide a nice solution to the issue raised at http://ask.sagemath.org/question/1816/visualize-vector-field-with-singularities.

This would be good. There are two options for this.
I'm not sure how the second one could even happen. But the first one requires some non-trivial changes to matplotlib.quiver (since currently scale is an attribute only), and probably should be sent upstream if done.