17

I am trying to have two panels, the left showing a graphic and two locators, the right one a zoomed-in version in the area defined by the locators.

I've tried

ClearAll[mndpt];
mndpt = Compile[{{c, _Complex}, {maxiter, _Integer}},
   Module[{z, iters},
        iters = 0.;
        z = c;
            While[(iters < maxiter) && (Abs@z < 2),
                iters++;
                z = z^2 + c];
        Sqrt[iters/maxiter]],
   {{z, _Complex}},
   CompilationTarget \[Rule] "C",
   RuntimeOptions \[Rule] "Speed"];

and do

Manipulate[
 Grid[
  {{DensityPlot[mndpt[x + y*I, 200],
        {x, -2, 1}, {y, -1.5, 1.5},
        PlotRange \[Rule] {0, 1}, PlotPoints \[Rule] 80, 
     ColorFunction \[Rule] "Rainbow"],
    DensityPlot[mndpt[x + y*I, 200],
        Dynamic@{x, p1[[1]], p2[[1]]}, Dynamic@{y, p1[[2]], p2[[2]]},
        PlotRange \[Rule] {0, 1}, PlotPoints \[Rule] 80, 
     ColorFunction \[Rule] "Rainbow"]}}],
 {{p1, {-1, -1}}, Locator}, {{p2, {0, 1}}, Locator}]

The right panel does not then work: enter image description here

My question is, why is this so? As you can see, it complains that "DensityPlot::pllim: Range specification {x,-1,0} is not of the form {x, xmin, xmax}. " which I find puzzling. In fact I am generally puzzled. What is going on? Some sort of scoping issue? Evaluation issue? And how can I get it to work? This is probably simple, but I never really understood this frontend stuff.

EDIT: It turns out that this question was due to a (hopefully momentary) sharp increase in stupidity on my part. As pointed out by Simon in a comment, removing the two Dynamics (which I had added in a blind effort to make this work) makes everything work fine. That is,

    Manipulate[
 Grid[
  {{DensityPlot[mndpt[x + y*I, 200],
        {x, -2, 1}, {y, -1.5, 1.5},
        PlotRange \[Rule] {0, 1}, PlotPoints \[Rule] 80, 
     ColorFunction \[Rule] "Rainbow"],
    DensityPlot[mndpt[x + y*I, 200],
        {x, p1[[1]], p2[[1]]},{y, p1[[2]], p2[[2]]},
        PlotRange \[Rule] {0, 1}, PlotPoints \[Rule] 80, 
     ColorFunction \[Rule] "Rainbow"]}}],
 {{p1, {-1, -1}}, Locator}, {{p2, {0, 1}}, Locator}]

does the right thing:

enter image description here

So, who knows why else I did the first few times so that it didn't work.

On the other hand, the message in the original case, namely, "DensityPlot::pllim: Range specification {x,-1,0} is not of the form {x, xmin, xmax}. " was more puzzling. I think it's been explained by Leonid, also in a comment (in brief, try ClearAttributes[Dynamic, ReadProtected] then ??Dynamic and you can see that there is a definition Dynamic/:MakeBoxes[BoxForm`x$_Dynamic,StandardForm]:= etc). As my understanding of frontend programming is negligible I won't try to explain it here, so if anybody does post an answer explaining that, it would be appreciated.

acl
  • 6,490
  • 1
  • 27
  • 33
  • 5
    Drop the two `Dynamic`s and everything works fine. – Simon Jul 17 '11 at 12:03
  • 1
    @Simon oh wow, thanks! I had actually put them there because "it did not work" and I started adding stuff randomly until it worked. Who knows what I'd done... Put your comment as an answer so I can accept it. Also, if you have any idea why the `Dynamic`s mess it up, I'd like to know. – acl Jul 17 '11 at 12:17
  • @Simon OK, it probably is because `Dynamic` has attribute `HoldFirst`. Or? – acl Jul 17 '11 at 14:16
  • @acl I think `Dynamic` is used for presentation purposes and possibly to trigger side effects in some variables in code it encloses, but it is not an invisible wrapper. Try this, for example: `n = 5; Table["test", {Dynamic[n]}]`. So, while `Dynamic` is supposed to be wrapped around code which you want to make dynamic, objects wrapped in `Dynamic` have a head `Dynamic`, and should not generally be used in places where the original objects were used. In other words, if `n` is an integer say, `Dynamic[n]` is not - it is just `Dynamic[n]`. – Leonid Shifrin Jul 17 '11 at 15:30
  • @Leonid yes, but I do not see how the message is then generated. Let me think about this – acl Jul 17 '11 at 15:39
  • 1
    @acl `Dynamic` (as many other commands) has `MakeBoxes` redefined on it via `UpValues` (you can see them once you remove the `ReadProtected` attribute from `Dynamic`). This should affect usage and error messages as well. – Leonid Shifrin Jul 17 '11 at 15:58
  • @Leonid You're absolutely right. What I couldn't understand is why the message showed the `{x,-1,0}` form, which I guess is explained by `ClearAttributes[Dynamic, ReadProtected]` followed `??Dynamic`. Excellent. Now I'll edit my question, and I hope either you, Simon or both will post answers so I can upvote/accept something :) – acl Jul 17 '11 at 18:11
  • 3
    @acl I'd be happy if Simon posts an answer, since it was him who answered the question. Then, either he incorporates some part of our discussion in his answer, or I could do it by editing his answer. – Leonid Shifrin Jul 17 '11 at 18:23
  • @Leonid: Do you want to write the answer? Your comments give me enough hints to work out what was happening, but they also reveal that you understand the issue much better than me. (But then, that's probably true for most of the SO answers I post). I just thought the extra `Dynamic`s were unnecessary, since the whole first argument in `Manipulate` is automatically wrapped in `Dynamic` (or something similar). – Simon Jul 17 '11 at 22:04
  • @Simon Thanks, but I wouldn't feel good writing an answer given that you answered the main part, and my comments only made some things more explicit. So, please do post your answer, if you don't mind of course. I am sure your answer will be more than adequate. And please incorporate any part of this comment-based discussion that you will consider relevant. – Leonid Shifrin Jul 18 '11 at 09:02
  • Just for curiosity, how to get the Locator on the second graph? – mikuszefski Jul 19 '11 at 09:01
  • @mikuszefski do you mean how to add locators on the plot on the right on the last panel? you'd need to add them explicitly. or do you mean something else? – acl Jul 19 '11 at 09:53
  • @acl, you got me right, I mean putting the locators to the right instead of the left panel---assume that you want the complete image on the right and the zoom on the left. Actually, I was a little bit surprised that the Locator is not over the full Grid but the first element of the Grid is chosen. So what is Manipulate doing here? – mikuszefski Jul 19 '11 at 11:23
  • 0 down vote @simon Perhaps you could post your comment as ananswer so that acl can accept it? It's now unnecessarily on the top of the unanswered questions list. – Sjoerd C. de Vries Aug 20 '11 at 11:54
  • @Sjoerd & acl: I'd completely forgotten about this! OK, I'll construct that answer I didn't really promise... – Simon Aug 20 '11 at 13:20
  • @simon great! BTW I just saw this '0 down vote' in my comment. I inadvertently posted the comment as an answer, discovered my mistake, copied the answer to the comment and apparently got the 0 vote added one way or another. – Sjoerd C. de Vries Aug 20 '11 at 13:52

1 Answers1

5

As discussed in the comments to the question, the code works fine if the Dynamics are removed from the ranges in the second DensityPlot. The Dynamics are not normally needed in the body of a Manipulate as it is automatically wrapped in a dynamic construct. Although, for a more fine grained control of which parts of an expression update, it can be useful to use Dynamic inside of a Manipulate.

The reason an error was created was because the range of a plot should be of the form {x, xmin, xmax} with x a Symbol and xmin and xmax numeric. Wrapping Dynamic around the list changes the head and breaks the plot.

The reason that the error was not obvious to spot is because the error message was a little confusing:

Range specification {x,-1,0} is not of the form {x, xmin, xmax}.

Which, on the surface looks crazy, but makes sense once you realise (as pointed out by Leonid) that Dynamic is a wrapper that has a MakeBoxes definition that makes it invisible when outputted to the notebook. To see this, look at

In[1]:= FormatValues[Dynamic]
Out[1]= {HoldPattern[MakeBoxes[BoxForm`x$_Dynamic, StandardForm]] :> (DynamicModule; 
           DynamicDump`ControlToBoxes[BoxForm`x$, StandardForm]), 
        <<snip: same but for TraditionalForm>>}

and ControlToBoxes in turn, creates a DynamicBox object. This can also be seen by entering Dynamic[x] and using the cell menu or shortcut to Show Expression of the produced output cell - you can also look at the underlying expression of the error message and see the DynamicBox construction there. It's also possible to Unprotect and remove the MakeBoxes definition of Dynamic, but that breaks most of the dynamic functionality in Mathematica...


Finally, here's my version of the code:

mndpt = Compile[{{c, _Complex}, {maxiter, _Integer}},
   Module[{z = c, iters = 0.0},
    While[(iters < maxiter) && (Abs@z < 2), iters++; z = z^2 + c];
    Sqrt[iters/maxiter]], CompilationTarget -> "C", 
   RuntimeOptions -> "Speed"];

opts = Sequence[PlotPoints -> 80, ColorFunction -> "Rainbow", 
   ImageSize -> Medium, ImagePadding -> {{30, 5}, {20, 5}}];

fixed = DensityPlot[mndpt[x + y*I, 200], {x, -2, 1}, {y, -1.5, 1.5}, 
   PlotPoints -> 120, Evaluate[opts]];

Manipulate[Grid[{{fixed, DensityPlot[mndpt[x + y*I, 200],
   {x, p[[1, 1]], p[[2, 1]]}, {y, p[[1, 2]], p[[2, 2]]}, Evaluate[opts]]}}],
 {{p, {{-1, -1}, {0, 1}}}, Locator, ContinuousAction -> False}]

output of the above

Simon
  • 14,631
  • 4
  • 41
  • 101
  • 1
    By coincidence I saw this almost immediately after you submitted it. It appears that I upvoted and accepted your answer 14 seconds after you submitted it, which I suspect must be a record! – acl Aug 20 '11 at 14:48
  • 1
    @acl: This just earned me the [Revival Badge](http://stackoverflow.com/badges/837/revival?userid=421225) - it pays to be lazy! – Simon Aug 21 '11 at 06:58