Проблема динамической интерактивности
Я пытаюсь иметь две панели, слева - графические и два локатора, а справа - увеличенную версию в области, определяемой локаторами.
Я пробовал
ClearAll[mndpt];
mndpt = Compile[{{c, _Complex}, {maxiter, _Integer}},
Module[{z, iters},
iters = 0.;
z = c;
While[(iters < maxiter) && ([email protected] < 2),
iters++;
z = z^2 + c];
Sqrt[iters/maxiter]],
{{z, _Complex}},
CompilationTarget \[Rule] "C",
RuntimeOptions \[Rule] "Speed"];
и 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],
[email protected]{x, p1[[1]], p2[[1]]}, [email protected]{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}.", Которую я нахожу загадочной. На самом деле я вообще озадачен. Что происходит? Какой-то вопрос? Вопрос оценки? И как я могу заставить его работать? Это, вероятно, просто, но я никогда не понимал этого внешнего вида.
EDIT: Оказывается, этот вопрос был вызван (надеюсь, мгновенным) резким увеличением глупости с моей стороны. Как отметил Саймон в комментарии, удаление двух 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]
then ??Dynamic
, и вы увидите, что есть определение Dynamic/:MakeBoxes[BoxForm`x$_Dynamic,StandardForm]:=
и т.д.). Поскольку мое понимание интерфейса программирования пренебрежимо мало, я не буду пытаться объяснить это здесь, поэтому, если кто-нибудь опубликует ответ, объясняющий это, было бы полезно.
Ответы
Ответ 1
Как обсуждалось в комментариях к вопросу, код работает нормально, если Dynamic
удаляются из диапазонов во втором DensityPlot
. Dynamic
обычно не нужны в теле 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) && ([email protected] < 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]()