17
$\begingroup$

I apologize if this is a obvious question and answer, I don't often use Mathematica to display plots or graphics in general to be honest. So, I was tutoring my cousin yesterday in relation to Polar functions and decided to bring up Mathematica to illustrate some of the ideas we were discussing. I quickly typed a one line command into Mathematica 8 and got an odd result. When rendering a polar function, Mathematica took a few seconds to make it smooth. Prior to this it has too many lines (see picture, before is on left and after is on the right.)

The code is:

Manipulate[PolarPlot[Sin[nS*t], {t, -5 Pi, 5 Pi}], {nS, 1, 20, 1}]

Mathematica graphics

Does anyone know why this is happening and if there is a way to make Mathematica render smooth at first?

$\endgroup$
1
  • 2
    $\begingroup$ In any case Manipulate[PolarPlot[Sin[nS*t], {t, -Pi, Pi}], {nS, 1, 20, 1}] is much better $\endgroup$ Commented Jul 8, 2012 at 19:05

3 Answers 3

22
$\begingroup$

This is done intentionally to update the plot quickly as you move the slider. Manipulate changes the setting for PerformanceGoal (via $PerformanceGoal) to "Speed" while you move the slider, then to "Quality" after you let go. This is seen in this simple demonstration:

Manipulate[{n, $PerformanceGoal}, {n, 0, 1}]

If you want the final quality while dragging at the expense of update speed you can give an explicit PerformanceGoal -> "Quality":

Manipulate[
 PolarPlot[Sin[nS*t], {t, -5 π, 5 π}, 
  PerformanceGoal -> "Quality"], {nS, 1, 20, 1}]

Alternatively you can take manual control of this process with ControlActive, and specify the PlotPoints that are used while dragging and after release:

Manipulate[
 PolarPlot[Sin[nS*t], {t, -5 π, 5 π}, 
  PlotPoints -> ControlActive[50, 150]], {nS, 1, 20, 1}]

You can turn off updating while dragging altogether using ContinuousAction:

Manipulate[PolarPlot[Sin[nS*t], {t, -5 π, 5 π}],
  {nS, 1, 20, 1}, ContinuousAction -> False]

As belisarius comments you range for t is excessive: {t, -π, π} will not run multiple circuits. This will allow the plot to update much more quickly. I leave the original value in the examples above so that the effect is easier to observe.

$\endgroup$
11
  • $\begingroup$ +1 I think ContinuousAction -> False is the most direct answer to the question $\endgroup$ Commented Jul 8, 2012 at 19:47
  • $\begingroup$ @belisarius thanks for the vote, but I have to disagree on "most direct" -- he writes: "... render smooth at first?" I think that sounds like PerformanceGoal -> "Quality" :-) But options are good so I tried to give several. $\endgroup$
    – Mr.Wizard
    Commented Jul 8, 2012 at 21:08
  • $\begingroup$ I guess the OP is happy with the results of the (final) plots without the PerformanceGoal -> "Quality" option. In this case perhaps there is no much timing differences, but sometimes I've seen PerformanceGoal -> "Quality" made the plot much slower to calculate $\endgroup$ Commented Jul 8, 2012 at 21:24
  • $\begingroup$ @belisarius in that case you have the precise control of the second option: ControlActive. I'm covering all the bases here! $\endgroup$
    – Mr.Wizard
    Commented Jul 8, 2012 at 21:27
  • 1
    $\begingroup$ ControlActive was just what I was looking for. Thanks! $\endgroup$
    – Sonryell
    Commented Jul 9, 2012 at 3:35
7
$\begingroup$

Mr. Wizard's answer indeed solves the problem of the ugly display. What's left to add is perhaps the more general question of why this seemingly trivial drawing problem is so slow in the first place.

The whole point of a Manipulate slider is, after all, that you want to see immediate effects in real time. And the difference to ListAnimate is that you want the real-time response to be a computed result, not in general a pre-rendered frame (because then we wouldn't need Manipulate in the first place).

So one should investigate the factors that slow down the displayed object in your manipulate. In this case, it has to do with the fact that ParametricPlot and other plotting functions try to choose a clever set of plot points and then do an interpolation to draw a smooth line. But trying to be clever can cost you time.

So if you want to run your Manipulate on a slow computer and still want high quality, that will mean the response to the slider action will become very sluggish. The output will look nice at all times, but the user experience will be bad. So you're between a rock and a hard place, unless you get rid of the time consuming step in the plot, i.e., the refinement and interpolation.

The solution then boils down to replacing ParametricPlot by ListParametricPlot (with lowest InterpolationOrder -> 1 which is the default). This is actually what I do quite often with DensityPlots, too (replace by ListDensityPlot or even ArrayPlot or Image). It's usually faster.

Here is what that would look like in the above example (keeping the over-wrapped angle variable just for consistency with the original):

Manipulate[
 ListPolarPlot[
  Table[{t, Sin[nS*t]}, {t, -5 Pi, 5 Pi, Pi/(20 + 15 nS)}], 
  Joined -> True, InterpolationOrder -> 1], {nS, 1, 20, 1}]

You can leave out InterpolationOrder -> 1, but I put it in so you can compare what happens if it's replaced by InterpolationOrder -> 2.

In choosing the number of points to generate in the Table, I used the number of expected lobes as a parameter (the higher nS, the more detail we need). For this example, this doesn't give any speed advantage really, but I think it's worth keeping in mind when your functions get more complicated. The explicit choice of plot points in this list plot is essentially part of the user-interface design, in that you decide how much lag you like to accept for an increase in quality.

Edit

Here is an example of a polar plot where Manipulate becomes really painful - using PolarPlot but with a different function than given in the question. It's plotting the result of a numerical integration in "real time":

Manipulate[
 PolarPlot[NIntegrate[LaguerreL[nS, x], {x, 0, t}], {t, 0, 2 Pi}, 
  PlotPoints -> ControlActive[10, 60]], {nS, 1, 20, 1}]

Trying this on my machine, I can (with some patience) drag the slider to the max, but then have to wait quite some time for the final interpolated curve to appear. Then I try to drag the slider back to the left, and Mathematica becomes unresponsive for several seconds, not even drawing the ControlActive version of the plot. The CPU usage sticks at 100%. And this despite the fact that I limited even the high-quality number of plot points to 60.

Now delete the manipulate generated above and try the next one:

Manipulate[
 ListPolarPlot[
  Table[NIntegrate[LaguerreL[nS, x], {x, 0, t}], {t, 0, 
    2 Pi, Pi/30}], Joined -> True], {nS, 1, 20, 1}]

Again it takes just as much patience to drag the slider all the way to the right. The difference here is that I have used ListPolarPlot and therefore was able to forego any attempts at interpolation. This means that the plot looks more angular than in the previous example, even though the number of plot points is the same as above.

But at least the Manipulate now responds much faster when I try to drag the slider back down. I'm pushing the performance limits here, so one should add a disclaimer: save your work before trying this.

The point here is: Manipulate seems to be utterly useless for this admittedly contrived example unless we can turn off interpolation. To do so, I used the ListPolarPlot version because by default it does not attempt interpolation. This means the final curves won't look entirely smooth, but (a) they look the same while dragging as they do when finished, and (b) the interface doesn't go into a coma.

There may be ways of getting ListPlot to perform a better here, but as far as I know, ListPolarPlot is the most straightforward way to get the control I need here.

Edit 2

Another good way to speed up the PolarPlot without using ListPolarPlot is to add MaxRecursion -> 0. This suppresses the iterative refinement of the point set on which the function is evaluated - and the advantage is that you can combine it more easily with Mr. Wizard's other suggestions.

Here are two closely related links that use both the List...Plot approach and the MaxRecursion approach. Either one can be superior, depending on the situation:

$\endgroup$
9
  • $\begingroup$ I don't know if something about this has changed on verison 8, but for v7 I find this method has worse performance. In an effort to slow down my system I set the range of each to -15 Pi, 15 Pi and ImageSize -> 1000. Then, comparing this method to Manipulate[ PolarPlot[Sin[nS*t], {t, -15 Pi, 15 Pi}, PlotPoints -> ControlActive[800, 1500], ImageSize -> 1000], {nS, 1, 20, 1}] the latter renders faster and is of higher quality. $\endgroup$
    – Mr.Wizard
    Commented Jul 9, 2012 at 1:05
  • $\begingroup$ In your solution the perceived wait does seem to be shorter, but the actual wait for the final render is quite long. I used table spacing Pi/(300 + 35 nS) just now and see a lag that is longer while dragging, but no lag when I release it because the final quality is already there. So I can't tell really. $\endgroup$
    – Jens
    Commented Jul 9, 2012 at 1:19
  • $\begingroup$ If that is your metric of performance try: Manipulate[ PolarPlot[Sin[nS*t], {t, -15 Pi, 15 Pi}, PerformanceGoal -> "Quality", PlotPoints -> 200, ImageSize -> 1000], {nS, 1, 20, 1}] $\endgroup$
    – Mr.Wizard
    Commented Jul 9, 2012 at 1:26
  • $\begingroup$ BTW, I do like the ControlActive solution and upvoted it because the default can be so ugly that a casual user will likely thing something has gone wrong with the program. $\endgroup$
    – Jens
    Commented Jul 9, 2012 at 1:26
  • $\begingroup$ I want to vote for this answer but I cannot if it actually makes the situation worse. If you know of a clear example where this method is a large improvement I urge you to post a Q&A to that effect. :-) $\endgroup$
    – Mr.Wizard
    Commented Jul 9, 2012 at 1:29
6
$\begingroup$

When it takes a long time to generate each plot you can pregenerate the plots and wrap them in ListAnimate to be able to quickly switch between them without having to render the plot over and over again.


plots = PolarPlot[Sin[#*t], {t, -Pi, Pi}, PlotRange -> {{-1, 1}, {-1, 1}}] & /@ Range[1, 20];
ListAnimate[plots]

I like to put PlotRange in to keep the same scale on the axis.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.