MathGroup Archive 2012

[Date Index] [Thread Index] [Author Index]

Search the Archive

Manipulate auto re-evaluation logic puzzler

  • To: mathgroup at
  • Subject: [mg123939] Manipulate auto re-evaluation logic puzzler
  • From: Frank Iannarilli <frankeye at>
  • Date: Sun, 1 Jan 2012 02:26:41 -0500 (EST)
  • Delivered-to:
  • Reply-to: comp.soft-sys.math.mathematica at

Can someone please explain this extremely puzzling behavior of Manipulate[]? 
(can follow along by evaluating code later below):

In short, a first Button[] push invokes A & B, where B changes a TrackedSymbols variable ("plots") that induces display update. But a second button push fails to induce display update, when it seemingly should. 

My Manipulate cell generates both Button[] and the usual Control[] activated interactions. The Button[] executes both processImage[] AND genPlots[] Modules defined within the Manipulate. processImage[] does expensive processing on an externally "passed-in" Global` variable named "image" to generate the intermediate result processedImage, which is localized to the Manipulate. User adjustment of the Control[] activates cheap analysis "post-processing" by genPlots[] on this intermediate result.

So please evaluate the later-below defined cells, as follows:
  testMyPatience[]:=Manipulate[... (* Manipulate cell definition *)
  image= (the first of the two image= cells)

Now push the Process! button - displayed results appear.

Now evaluate the second of the two image= cells (change from random to Sine image):

Now push the Process! button - the display is unchanged!! (Yuck!)

But now push the L2 control - the display updates to show the newer image results! 

Yet the Button[] function processImage[] is careful to invoke plots=genPlots[] as its last instruction. And "plots" is included in TrackedSymbols. With my full-scale code, I can see that pressing the Process! button does actually result in computation (30 seconds of it) - how can Manipulate not see "plots" getting modified upon Button-push, and therefore execute the appropriate Refresh? 

John Fultz, are you there? :-)


image = Table[RandomReal[], {32}, {32}];


image = Table[Sin[i*j/64], {i, 1, 32}, {j, 1, 32}];

testMyPatience[] := Manipulate[
  (* image is in Global` namespace,
  and is "passed" by an external party. *)
  (* The actual processing of image is expensive which is why we have \
it button-activated. 
  It produces processedImage which can be analyzed repeatedly by \
genPlots[] for different controller settings w/
  o processedImage needing to be recomputed. *)(* This Button-
  activated Module modifies the external variables {firstTime,
  snapShot,processedImage}.  *)
  processButton[] :=
    firstTime = False;
    snapShot = image;
    (* Yields external variable pocessedImage *)
    processedImage = Transpose[image];
    (* Yields external plots *)
    plots = genPlots[];
  (* Take processedImage and post-
  process as desired into diagnostic graphics. 
  Preserve processedImage by treating as "read-only" -
  it is expensive to compute - the diagnostic results are not,
  and can be iterated for different settings,
  while preserving the expensive processedImage.  *)
  genPlots[] := Module[{touchedProcessedImage, g1, g2},
    (* Now change appearance of processedImage IAW chosen metric *)
    If[cmetric == "L2",
     touchedProcessedImage = processedImage^2];
    If[cmetric == "L1",
     touchedProcessedImage = Reverse[processedImage]];
    (* Now make graphics *)
    g1 = ListPlot3D[snapShot, PlotLabel -> "Image", PlotRange -> All];
    g2 = ListPlot3D[touchedProcessedImage, PlotLabel -> "touched",
      PlotRange -> All];
    (* Return *) GraphicsGrid[{{g1, g2}}, ImageSize -> 400]
  plots = If[Not[firstTime],
    "Hi trusty Mathematica weenie!"
  (* The last executable statement above must terminate with a comma,
  thus marking the division between the "action" and control/
  layout specification sections of the Manipulate[] *)
  (* >>>>>>> CONTROL/LAYOUT SECTION <<<<<<<<< *)
  Item[Style["Test My Patience", 16, Bold, Brown],
   Alignment -> Center],
  {{cmetric, "L1", "Plot Appearance"}, {"L1", "L2"}},
  Button["Process!", processButton[], Method -> "Queued"],
  (* Dummy control variables,
  which are actually variables we'd like to keep localized to within \
this Manipulate, or otherwise they'd leak out as session-
  global variables.  A good rule of thumb:
  if a variable is included in TrackSymbols, it better be localized. 
  True localizes variables associated with Controls.  *)
  {firstTime, ControlType -> None},
  {snapShot, ControlType -> None},
  {plots, ControlType -> None},
  {processedImage, ControlType -> None},
  (* Manipulate options *)
  LocalizeVariables -> True,
  (* Very Strange!!!  If we DON'T track processedImage,
  graphics don't update, even when processButton is pressed,
  which includes invocation of plots=genPlots[],
  AND we are tracking the dummy control variable "plots" !  *)
  TrackedSymbols :> {cmetric, firstTime, plots},
  ContinuousAction -> False, Initialization :> (firstTime = True)

  • Prev by Date: Re: PairedBarChart "Education and Training pay..."
  • Next by Date: Re: Right-clicking on animation crashes Mathematica
  • Previous by thread: Re: PairedBarChart "Education and Training pay..."
  • Next by thread: Surprising DSolve problem