проблема динамической интерактивности - PullRequest
17 голосов
/ 17 июля 2011

Я пытаюсь создать две панели: на левой панели изображены графика и два локатора, на правой - увеличенная версия в области, определенной локаторами.

Я пробовал

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"];

и сделать

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}]

Правая панель не работает: enter image description here

Мой вопрос: почему это так? Как видите, он жалуется на то, что «DensityPlot :: pllim: спецификация диапазона {x, -1,0} не имеет форму {x, xmin, xmax}.», Что я нахожу озадачивающим. На самом деле я в целом озадачен. Что здесь происходит? Какая-то проблема с ограничениями? Вопрос оценки? И как мне заставить его работать? Это, наверное, просто, но я никогда не понимал этого интерфейса.

РЕДАКТИРОВАТЬ: Оказывается, этот вопрос был из-за (надеюсь, мгновенный) резкое увеличение глупости с моей стороны. Как указал Саймон в комментарии, удалив два Dynamics (который я добавил в слепой попытке сделать эту работу) заставляет все работать нормально. То есть

    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}]

поступает правильно:

enter image description here

Итак, кто знает, почему еще я делал первые несколько раз, чтобы это не сработало.

С другой стороны, сообщение в исходном случае, а именно: «DensityPlot :: pllim: спецификация диапазона {x, -1,0} не имеет форму {x, xmin, xmax}.» Было более загадочным , Я думаю, что это было объяснено Леонидом, также в комментарии (вкратце, попробуйте ClearAttributes[Dynamic, ReadProtected], затем ??Dynamic, и вы можете видеть, что есть определение Dynamic/:MakeBoxes[BoxForm`x$_Dynamic,StandardForm]:= и т. Д.). Поскольку мое понимание программирования на внешнем интерфейсе незначительно, я не буду пытаться объяснить это здесь, поэтому, если кто-то опубликует ответ, объясняющий это, это будет оценено.

1 Ответ

5 голосов
/ 20 августа 2011

Как обсуждалось в комментариях к вопросу, код работает нормально, если Dynamic s удалены из диапазонов во второй DensityPlot. Dynamic s обычно не нужны в теле Manipulate, поскольку они автоматически заключаются в динамическую конструкцию. Хотя для более детального контроля над тем, какие части выражения обновляются, может быть полезно использовать Dynamic внутри Manipulate.

Причина ошибки была в том, что диапазон графика должен иметь форму {x, xmin, xmax} с x a Symbol и xmin и xmax числовым. Обтекание Dynamic вокруг списка меняет голову и нарушает сюжет.

Причина, по которой ошибка не была очевидна, заключается в том, что сообщение об ошибке немного сбивало с толку:

Спецификация диапазона {x, -1,0} не имеет форму {x, xmin, xmax}.

Что на первый взгляд выглядит безумно, но имеет смысл, как только вы осознаете (как указал Леонид), что Dynamic - это обертка, которая имеет определение MakeBoxes, которое делает ее невидимой при выводе на ноутбук. Чтобы увидеть это, посмотрите на

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

и ControlToBoxes, в свою очередь, создают объект DynamicBox. Это также можно увидеть, введя Dynamic[x] и используя меню ячейки или ярлык для Показать выражение созданной выходной ячейки - вы также можете посмотреть на основное выражение сообщения об ошибке и увидеть DynamicBox строительство там. Также возможно Unprotect и удалить определение MakeBoxes Dynamic, но это нарушает большинство динамических функций в Mathematica ...


Наконец, вот моя версия кода:

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

...