4

I have a list variable that I want to append new values from a normal distribution to after I click a button. It works in a simple case but not for the more complicated situation and I don't know why.

This works.. When I run it and press Start I can see the dynamic signal variable gets an extra '1' appended to the list every second.

signal = {};
DynamicModule[{task, μ, σ},
  task = CreateScheduledTask[AppendTo[signal, 1], 1];
  μ = 10;
  σ = 1;
  Panel[Grid[
    {{Button["Start", StartScheduledTask[task]], Null},
     {Button["Stop", StopScheduledTask[task]], Null},
     {"μ", Slider[Dynamic[μ], {0, 50}], Dynamic[μ]},
     {"σ", Slider[Dynamic[σ], {0, 10}], Dynamic[σ]}
  }, Dividers -> {False, {False, False, True}}]]
]

Dynamic[signal]

But what I'm actually interested in is appending a random variate from a normal distribution to the list. So I change the task variable to:

task = CreateScheduledTask[AppendTo[signal,
  RandomVariate[NormalDistribution[μ, σ]]], 1]

But this doesn't work. Nothing is appended to the list.

Edmund
  • 42,267
  • 3
  • 51
  • 143
Sean Lynch
  • 1,079
  • 5
  • 16

1 Answers1

2

I actually get an error message when I run your code with the RandomVariate task. It says:

StartScheduledTask::timnf: Specified task ScheduledTaskObject[Unique ID:5,Repetitions: ∞] is not found.

The reason why your original code does not work seems to be that the RandomVariate[...] function delays the evaluation of the task= part of your code and hence task is not properly defined when the Panel is created. I must admit I don't fully understand why things are not evaluated in the sequence they are written, given that there is no SetDelayed involved. Anyways, there are multiple ways around this:

1. Force immediate evaluation

signal = {};
DynamicModule[{μ, σ}, μ = 10;
 σ = 1;
 task = CreateScheduledTask[
   AppendTo[signal, 
    Evaluate[RandomVariate[NormalDistribution[μ, σ]]]], 
   1];
 Panel[Grid[{{Button["Start", StartScheduledTask[task]], 
     Null}, {Button["Stop", StopScheduledTask[task]], Null}, {"μ",
      Slider[Dynamic[μ], {0, 50}], Dynamic[μ]}, {"σ", 
     Slider[Dynamic[σ], {0, 10}], Dynamic[σ]}}, 
   Dividers -> {False, {False, False, True}}]]]

Dynamic[signal]

2. Define task in the global scope

signal = {};
DynamicModule[{μ, σ},
 μ = 10;
 σ = 1; 
 task = CreateScheduledTask[
   AppendTo[signal, 
    RandomVariate[NormalDistribution[μ, σ]]], 1];
 Panel[Grid[{{Button["Start", StartScheduledTask[task]], 
     Null}, {Button["Stop", StopScheduledTask[task]], Null}, {"μ",
      Slider[Dynamic[μ], {0, 50}], Dynamic[μ]}, {"σ", 
     Slider[Dynamic[σ], {0, 10}], Dynamic[σ]}}, 
   Dividers -> {False, {False, False, True}}]]]

Dynamic[signal]

3. Make sure task is defined in the initialization of the DynamicModule

signal = {};
DynamicModule[{task, μ, σ},
 Panel[Grid[{{Button["Start", StartScheduledTask[task]], 
     Null}, {Button["Stop", StopScheduledTask[task]], Null}, {"μ",
      Slider[Dynamic[μ], {0, 50}], Dynamic[μ]}, {"σ", 
     Slider[Dynamic[σ], {0, 10}], Dynamic[σ]}}, 
   Dividers -> {False, {False, False, True}}]],
 Initialization :> (
   μ = 10; σ = 1;
   task = 
    CreateScheduledTask[
     AppendTo[signal, 
      RandomVariate[NormalDistribution[μ, σ]]], 1];
   )]

Dynamic[signal]
Felix
  • 3,871
  • 13
  • 33
  • Hmmm. That doesn't work for me. I'm on version 9. Maybe the behavior's been changed in a later version you have? – Sean Lynch Jan 29 '17 at 03:16
  • It works in version 10 and 11. Please clarify the version in your question (e.g., add a version tag) if you are looking for a solution specifically for that version. – Felix Jan 29 '17 at 03:33
  • Ok yes it works for me in version 9. I had changed something that screwed it up when I retested it with your answer. – Sean Lynch Jan 29 '17 at 03:59
  • I think this has something to do with this question. I've updated my code to put the task in the Intialization option of the DynamicModule and it works. Can you update your answer to do it this way since I think this is probably the best way to do it. – Sean Lynch Jan 29 '17 at 04:02
  • Interesting... Now that it works the problem is that the μ and σ variables are not updated when changed with the slider. If I stop the task and then start it again, it chooses the new values for those variables but they are not tracked on the fly as it's adding new values. – Sean Lynch Jan 29 '17 at 05:01
  • I see. It looks like task is created with whatever values μ and σ have at the time of assignment and then any association to the variable names μ and σ is lost. That makes sense since that is exactly what Set is doing. However, even by defining task[μ_,σ_]:=... I can't make it use the values of μ and σ from the slider. The only way that works for me is to define those variables in the global context (and then it works also with the task= Set assignment). – Felix Jan 29 '17 at 05:15