6
$\begingroup$

This example is from the documentation under Monitor

data = {{0.18, -0.13}, {0.84, -0.06}, {0.05, 
    0.88}, {0.24, -0.63}, {0.67, 0.93}, {0.05, 0.88}, {0.65, 
    0.92}, {0.01, 0.99}, {0.17, -0.04}, {0.23, -0.55}};

model[{a_, k_, w_, p_}][x_] = a Exp[-k x] Sin[w x + p]

lp = ListPlot[data, PlotRange -> All]

I can successfully plot the steps using Monitor

Module[
 {
  vars = {a, k, w, p}
  },
 Monitor[
  FindFit[data, model[vars][x], vars, x,
   StepMonitor :> Pause[1.0]],
  Show[
   Plot[model[vars][x], {x, 0, 1}, PlotRange -> {-2, 2}],
   lp]
  ]
 ]

Mathematica graphics

Mathematica graphics

Mathematica graphics

I can print the results using StepMonitor

FindFit[data, model[{a, k, w, p}][x], {a, k, w, p}, x,
 StepMonitor :> Print[{a, k, w, p}]]

Mathematica graphics

As shown in the documentation I can extract the results using Reap and Sow.

steps = Reap[
  FindFit[data, model[{a, k, w, p}][x], {a, k, w, p}, x, 
   StepMonitor :> Sow[{a, k, w, p}]]]

Mathematica graphics

I can then use the steps to plot the results.

My question is not about how to plot the results.

My question is why when I use Plot as an argument to StepMonitor I get no result.

I made various attempts. One is shown below.

FindFit[data, model[{a, k, w, p}][x], {a, k, w, p}, x,
 StepMonitor :> CompoundExpression[
   Pause[1.0],
   Show[
    Plot[model[{a, k, w, p}][y], {y, 0, 1}, PlotRange -> {-2, 2}],
    lp
    ]
   ]
 ]

It gives me the results and takes much longer than running without the StepMonitor but no plots are shown on the screen.

I am confused as to why this happens.

$\endgroup$
4
$\begingroup$

Starting from Mathematica version 6 Show by default has no side effects. In your particular case it just returns the Graphics expression to StepMonitor which does not use it because the latter is designed only for working with functions which have side effects like Print (side effect is printing of the expression and nothing is returned as the output) or Set (side effect is setting new value for the variable and this new value is returned as the output). As Bob mentions, you can add side effect to Show by the DisplayFunction -> Print option. The same effect can be achieved by writing directly to "stdout" with DisplayFunction -> (Write["stdout", #] &) or by writing to the $Output channel: DisplayFunction -> (Write[$Output, #] &). But I personally prefer the Dynamic approach demonstrated by belisarius.

$\endgroup$
  • $\begingroup$ I added your comment to my answer. If you wish, I will remove it from my answer. In either case +1 $\endgroup$ – Bob Hanlon Sep 26 '15 at 0:03
5
$\begingroup$

You can put Print around the Show

data = {{0.18, -0.13}, {0.84, -0.06}, {0.05, 
    0.88}, {0.24, -0.63}, {0.67, 0.93}, {0.05, 0.88}, {0.65, 
    0.92}, {0.01, 0.99}, {0.17, -0.04}, {0.23, -0.55}};

model[{a_, k_, w_, p_}][x_] = a Exp[-k x] Sin[w x + p];

lp = ListPlot[data, PlotRange -> All, PlotStyle -> Red];

FindFit[data, model[{a, k, w, p}][x], {a, k, w, p}, x, 
 StepMonitor :> 
  Print[Show[
    Plot[model[{a, k, w, p}][y], {y, 0, 1}, PlotRange -> {-2, 2}], 
    lp]]]

enter image description here

(*  {a -> 0.997279, k -> 0.104408, w -> -9.41643, p -> 1.56093}  *)

EDIT: Or explicitly set the DisplayFunction option for Show to Print

FindFit[data, model[{a, k, w, p}][x], {a, k, w, p}, x, 
 StepMonitor :> 
  Show[Plot[model[{a, k, w, p}][y], {y, 0, 1}, PlotRange -> {-2, 2}], 
   lp, DisplayFunction -> Print]]

EDIT 2: Comment by Alexey Popkov added for clarity.

"Show by default has no side effects: it just returns the Graphics expression to StepMonitor which does not use it because the latter is designed only for working with functions which have side effects like Print (side effect is printing of the expression and nothing is returned into the $Output channel) or Set (side effect is setting new value for the variable, output is the new value of the variable). As @Bob mentions, you can add side effect to Show by the DisplayFunction -> Print option." – Alexey Popkov

$\endgroup$
  • $\begingroup$ Your Print solution works well and produces a permanent record. Do you have a suspicion as to why simply using Show displays nothing? $\endgroup$ – Jack LaVigne Sep 25 '15 at 21:04
  • $\begingroup$ @JackLaVigne - perhaps StepMonitor changes the DisplayFunction since explicitly setting DisplayFunction results in an output from Show. $\endgroup$ – Bob Hanlon Sep 25 '15 at 21:28
  • $\begingroup$ @JackLaVigne Show by default has no side effects: it just returns the Graphics expression to StepMonitor which does not use it because the latter is designed only for working with functions which have side effects like Print (side effect is printing of the expression and nothing is returned into the $Output channel) or Set (side effect is setting new value for the variable, output is the new value of the variable). As @Bob mentions, you can add side effect to Show by the DisplayFunction -> Print option. $\endgroup$ – Alexey Popkov Sep 25 '15 at 23:38
  • $\begingroup$ @AlexeyPopkov Thank you so much. Totally confused as to what was going on. $\endgroup$ – Jack LaVigne Sep 25 '15 at 23:47
  • $\begingroup$ @BobHanlon If you agree with Alexy Popkov's comment, could you add it to the answer? $\endgroup$ – Jack LaVigne Sep 25 '15 at 23:48
4
$\begingroup$

This works:

Dynamic@f
FindFit[data, model[{a, k, w, p}][x], {a, k, w, p}, x, 
 StepMonitor :> CompoundExpression[Pause[.5], 
   f = Show[Plot[model[{a, k, w, p}][y], {y, 0, 1}, PlotRange -> {-2, 2}],  lp]]]

Mathematica graphics

$\endgroup$
  • $\begingroup$ Correct. The Dynamic is outside of the FindFit. My questions is why the Show doesn't display inside the StepMonitor. $\endgroup$ – Jack LaVigne Sep 25 '15 at 14:26
  • $\begingroup$ @JackLaVigne The problem is that (for some unknown reason to me) the DisplayFunction is being redirected to nul in the current document. Try for example: $\endgroup$ – Dr. belisarius Sep 25 '15 at 14:36
  • $\begingroup$ obj = CreateDocument[]; FindFit[data, model[{a, k, w, p}][x], {a, k, w, p}, x, StepMonitor :> CompoundExpression[Pause[.5], Show[Plot[model[{a, k, w, p}][y], {y, 0, 1}, PlotRange -> {-2, 2}], lp, DisplayFunction -> (CreateDocument[#, obj] &)]]] $\endgroup$ – Dr. belisarius Sep 25 '15 at 14:36
  • $\begingroup$ Explicitly setting DisplayFunction->Identity doesn't help. It looks like a strange quirk. I am happy with using Dynamic outside of StepMonitor. $\endgroup$ – Jack LaVigne Sep 25 '15 at 15:13
  • $\begingroup$ @belisarius Your interpretation is not quite correct: actually the output of Show is returned to StepMonitor which simply drops it. It is "by design", see also this comment. $\endgroup$ – Alexey Popkov Sep 25 '15 at 23:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.