Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
Added fplot to Axes subclass.#737
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
eps = 1e-10 | ||
tol = kwargs.pop('tol', None) | ||
n = kwargs.pop('tol', None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Bug right there. Also, it would be more efficient to dokwargs.pop('n', 50)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Thanks for the find. Good spot.
On the whole, I like the idea. It would be great if the concept could be generalised to support different types of functions (parametric equations, 2d functions [for contouring and such like]), and concepts such as limiting the domain of a function (e.g. Of course, this is bread and butter stuff forsympy. |
Interesting idea, but I am not convinced that this belongs here. The computational part feels like it belongs in numpy or scipy. The user could just call that, have it return the data and then feed that into what ever plotting software they may want. Having the computational part elsewhere would also allow a user to analyze the numerical results and/or save the results. My 2 cents |
Thanks for the feedback@pelson and@WeatherGod. I can see both your points, and I have arguments in favour and against both of them. Perhaps we could decide what the best way to proceed is. Firstly, the issue I was trying to address (#330) was a request for Matlab's Secondly, I completely agree that support for hairier functions like Thirdly, the problem with having the computational part in NumPy or SciPy is: how would one then obtain the discontinuities (see my second point above)? If the NumPy function were just to return an array of points, and that was passed to So I guess we have a couple of options regarding the next steps in this:
I'm kind of new to contributing to this library, so I'm probably not the best person to decide. Could perhaps one of you suggest what we should do? |
Just some food for thought. You can plot a discontinuity with a single line2d. Just put a NaN value there and the line will be broken up. |
Conflicts:CHANGELOG
Conflicts:CHANGELOG
Having an fplot is a long requested feature so I'm inclined to incorporate this or some version of it. I would like to see a pyplot interface function and an example along with this PR, so it will be easier to test and explore. @fperez has done a lot of work on adaptive sampling in his former life; I don't feel well-qualified to comment on the algorithm being used here, but I am not averse to including computation in mpl if there is nothing suitable in numpy. In general, we have had a lot of success in mpl by putting out something that works in many/most cases even if it is not perfect, and over time users and domain experts will fill in the gaps. We also have the option of conditionally utilizing scipy if they have some nice adaptive sampling algorithms that we could rely on if present else fall back on our own. I think some work improving the algorithm will be needed, addressing the comments above, eg for functions with singularities, and the speed feels pretty slow, eg there is a noticeable delay in ax.fplot(np.exp, [0, 10]) so we probably want to consider either utilizing a faster algorithm or doing some of this in extension code, |
@@ -6304,6 +6305,9 @@ def quiver(self, *args, **kw): | |||
return q | |||
quiver.__doc__ = mquiver.Quiver.quiver_doc | |||
def fplot(self, f, limits, *args, **kwargs): | |||
return mfplot.fplot(self, f, limits, *args, **kwargs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This function needs a doc string -- take a look at contour to see how we share docstrings between module helper code and the axes wrapper funcs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Thanks! I'll make sure to add that.
Ok, so I have been surfing the intertubes this weekend to do some research about the best algorithm for the adaptive sampling. This comes from@jdh2358's comment on it taking a while to plot
These issues will be the downfall of this algorithm and need to be addressed. Now, I found athread that@jdh2358 posted to asking for advice from the SciPy/NumPy community regards adaptive sampling algorithms. Though the link in there (presumably to someone's code) didn't work for me. Interestingly, I also came acrossthis thread advising a user on plotting (adaptively) an expensive and non-analytic function. There, the advice given was to coarsely sample Now, Matlab's approach to
External code to compute the refinements would be a great idea in terms of improving speed, but I think I should at least make some attempt at making the mpl implementation faster before doing so. These are all just my opinions though, and I'm not the most experienced at this, so external suggestions arealways welcome. |
Hey Damon, regarding looking at Octave code: you have to be careful here. Octave is GPL, and matplotlib is PSF compatible, which means we cannot use GPL'd code. Seehttp://matplotlib.sourceforge.net/devel/coding_guide.html#license-discussion I have contacted Denis Bzowy, the original author of the adaptive spline code linked on dropbox in the 2009 scipy thread you referred to that is now a stale link, to see if he can provide us a copy of the code he was working on, and perhaps collaborate with us on the current implementation of fplot. II'll respond here when I hear back. In the meantime, please keep working on the algorithm you have to improve the performance in regular cases like exp(x) over [0, 10] and in special cases where there are singularities. Some of the performance problems can likely be solved by moving the code into C/C++, but having the right algorithm will help more. Thanks again, |
I'm not sure how well known the Mandlebrot example at In terms of implementation, it seems like it would be rather nice if the functionality of |
Very preliminary, but when I scale the minimum step size as a function of the domain size (just linear scaling), I get a 3x-4x speed-up when plotting@jdh2358's example: $time python fplottest.py# no scalingreal 0m7.573suser 0m7.260ssys 0m0.209s$time python fplottest.py# scalingreal 0m2.427suser 0m2.184ssys 0m0.203s |
Nice performance improvements! Just wanted to let you know I have not heard yet from Denis Bzowy, the original author of the adaptive spline code. |
Plotting functionality for Python callables, ala Matlab's 'fplot'function.An adaptive step-size is used. Smaller step sizes are used when thegradient of the function is larger.Only one callable is supported so far, it would be desirable to supportan array/list of callables and plot them all simultaneously.There are some unresolved problems. One is the inability to deal withthe scenario when f(x) is undefined for some x.
Reduces the amount of unnecessary computation by ignoring partitionsizes that the user won't see with longer domains.
The old method computed 'left' and 'right' gradients. These are the samefor a linear approximation, which is what Line2D is anyway.I have also stored some function values that are used later in thealgorithm. This is good if f is expensive to compute.The above changes to reduce computation time by 20%.
Now we call axes.plot with stored values of f instead of calling f on x.This will improve performance when f is an expensive function.
When we find singularities, replace the function values with NaN so theyappear as separate Line2Ds on the plot
I'm going to close this and work on@pelson's suggestion of encapsulating |
Plotting functionality for Python callables, ala Matlab's 'fplot' function.
An adaptive step-size is used. Smaller step sizes are used when the gradient of the function is larger. The heavy lifting for the step size is done by the fplot function. Then x,y coordinates are created and passed directly to the plot function in the Axes subclass. As a result, all of the usual kwargs are still supported.
Only one callable is supported so far, it would be desirable to support an array/list of callables and plot them all simultaneously.
There are some unresolved problems. One is the inability to deal with the scenario when f(x) is undefined for some x.
The reason I've tried to make a start on this is to address issue#330. I'll need some help resolving some of the issues I've documented in the source code, but I'd like some feedback on this initial effort.