2011-07-17 9 views
17

Estoy intentando tener dos paneles, el izquierdo mostrando un gráfico y dos localizadores, el derecho una versión ampliada en el área definida por los localizadores.problema de interactividad dinámica

He intentado

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

y hacer

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

El panel de la derecha no lo hace entonces funcionar: enter image description here

Mi pregunta es, ¿por qué es esto así? Como puede ver, se queja de que "DensityPlot :: pllim: Especificación de rango {x, -1,0} no es de la forma {x, xmin, xmax}." Lo cual me resulta desconcertante. De hecho, generalmente estoy desconcertado. Que esta pasando? ¿Algún tipo de problema de alcance? ¿Problema de evaluación? ¿Y cómo puedo hacer que funcione? Esto es probablemente simple, pero nunca entendí realmente este frontend.

EDITAR: Resulta que esta pregunta se debió a un (agudo) momentáneo aumento en la estupidez de mi parte. Como señaló Simon en un comentario, eliminar los dos Dynamics (que había agregado en un esfuerzo ciego para que esto funcione) hace que todo funcione bien. Es decir,

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

hace lo correcto:

enter image description here

Entonces, ¿quién sabe qué otra cosa que hice las primeras veces de modo que no funcionaba.

Por otro lado, el mensaje en el caso original, a saber, "DensityPlot :: pllim: especificación de rango {x, -1,0} no es de la forma {x, xmin, xmax}." Era más misterioso. Creo que ha sido explicado por Leonid, también en un comentario (en resumen, prueba ClearAttributes[Dynamic, ReadProtected] luego ??Dynamic y puedes ver que hay una definición Dynamic/:MakeBoxes[BoxForm`x$_Dynamic,StandardForm]:=, etc.). Como mi comprensión de la programación frontend es insignificante, no trataré de explicarla aquí, así que si alguien publica una respuesta explicando eso, sería apreciado.

+5

Suelta los dos 'Dynamic's y todo funciona bien. – Simon

+1

@Simon oh wow, gracias! Los había puesto allí porque "no funcionó" y comencé a agregar cosas al azar hasta que funcionó. Quién sabe lo que hice ... Pon tu comentario como respuesta para poder aceptarlo. Además, si tiene alguna idea de por qué el 'Dynamic' lo estropea, me gustaría saberlo. – acl

+0

@Simon OK, probablemente sea porque 'Dynamic' tiene el atributo' HoldFirst'. ¿O? – acl

Respuesta

5

Como se discutió en los comentarios a la pregunta, el código funciona bien si los Dynamic s se eliminan de los rangos en el segundo DensityPlot. Los Dynamic s normalmente no se necesitan en el cuerpo de un Manipulate ya que se envuelve automáticamente en una construcción dinámica. Aunque, para un control más detallado de qué partes de una actualización de expresión, puede ser útil usar Dynamic inside of a Manipulate.

La razón se creó un error fue debido a que el rango de una parcela debe ser de la forma {x, xmin, xmax} con x un Symbol y xmin y xmax numérico. Envolviendo Dynamic alrededor de la lista cambia la cabeza y rompe la trama.

La razón de que el error no era obvio de detectar es porque el mensaje de error era un poco complicado:

Especificación de rango {x, -1,0} no es de la forma {x, xmin, xmax}.

Lo cual, en la superficie parece una locura, pero tiene sentido una vez que se da cuenta (como se ha señalado por Leonid) que Dynamic es una envoltura que tiene una definición MakeBoxes que lo hace invisible cuando se da salida a la portátil. Para ver esto, mira

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

y ControlToBoxes a su vez, crea un objeto DynamicBox. Esto también se puede ver ingresando Dynamic[x] y utilizando el menú de la celda o el acceso directo a Show Expression de la celda de salida producida; también puede ver la expresión subyacente del mensaje de error y ver allí la construcción DynamicBox. También es posible Unprotect y retire la definición MakeBoxes de Dynamic, pero que rompe la mayor parte de la funcionalidad dinámica en Mathematica ...


Por último, aquí está mi versión del código:

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

+1

Por coincidencia, vi esto casi inmediatamente después de haberlo enviado. Parece que subí y acepté tu respuesta 14 segundos después de que la enviaste, ¡que sospecho que debe ser un registro! – acl

+1

@acl: Esto me acaba de otorgar el [Revival Badge] (http://stackoverflow.com/badges/837/revival?userid=421225) - ¡vale la pena ser flojo! – Simon