cortex-lab / Rigbox

A MATLAB toolbox for running behavioral neuroscience experiments and managing data
GNU General Public License v3.0
33 stars 16 forks source link

[Signals] using .delay inside of cond() or | (or) blocks evaluation of remaining predicates #279

Closed dbirman closed 4 years ago

dbirman commented 4 years ago

Describe the bug I'm not sure if I'm using these functions incorrectly, but as you'll see below I believe that calling .delay inside of a conditional causes it to fail to evaluate the remaining predicates.

To Reproduce

% setup a simple network
net = sig.Net;
os1 = net.origin('input 1');
os2 = net.origin('input 2');
% create a conditional, where posting true to os2 should create an output
out = output(cond(os1.delay(5),true,os2,true));
% posting fails to create an output
os2.post(1);
% posting to the delayed signal also fails
os1.post(1);
% same conditional but using "|"
out = output((os1.delay(5)) | os2);
os2.post(1)
os1.post(1)
% remove the delay
out = output(os1 | os2);
 os2.post(1)
   1

os1.post(1)
   1

Expected behavior The docs say that if any predicate in cond or | are true, then the function should evaluate to the value of the first true predicate. I guess delay is making is so the signal doesn't have a value yet, so it doesn't evaluate fully?

Desktop (please complete the following information): Code is the most recent update (2.5) Matlab 2019b

k1o0 commented 4 years ago

Hi Dan, thanks for the feedback. This aspect of Signals isn't very well documented at the moment. The delay signal works differently to others because it relies on another method, sig.Net/runSchedule. When runSchedule is called, all delay signals are updated if their delay time is up. When running an experiment via an expDef function, this runSchedule method is called during the experiment while loop (the same loop that updates the input and time signals). When playing with signals in the command window you have to call this method yourself: net.runSchedule.

Most signals don't update unless all their inputs have a value. The cond method stops evaluating at the condition that hasn't updated, so the order of your conditions is important, e.g.

% This will update because os2 is before os1 in cond
out = cond(os2, true, os1.delay(5), true).output()
os2.post(1)
  1

I've added some useful functions for playing with Signals in the command window. These can be found in +sig/+test. If you create a signal using sig.test.sequence, it will update at a given interval, and update any delay signals too, e.g.

% Update with values 1-5 every 1 second, starting after 5 seconds
os1 = sig.test.sequence(1:5, 1, 5);
os2 = os1.delay(5);
out = output(cond(os1.delay(1) > 3, 'first', os2 > 1, 'second'));

More (incomplete) info on the schedule can be found here.

You can find examples of these new functions here: https://github.com/cortex-lab/Rigbox/blob/documentation/docs/scripts/using_signals.m git checkout origin/documentation -- docs/scripts/using_signals.m

dbirman commented 4 years ago

Thanks for the explanation for this, what's going on makes sense and I think it would be helpful to have an example somewhere in the tutorials showing what happens when you delay signals and prevent a second signal from being evaluated.

Actually, even easier might be to change the documentation in sig.Signal for the cond() and or() functions. Even just adding the sentence you wrote above "Signals don't update unless all their inputs have a value." and something like "e.g. including a .delay() will prevent the function from evaluating further predicates" would probably solve this for someone who runs into it in the future.

k1o0 commented 4 years ago

Returning to this, I spent a lot of time last week creating some much better guides on Signals. I hope these will make things much clearer for you. If you have questions or feedback please do let me know so I can improve the documentation further. The guides can all be found at https://cortex-lab.github.io/Rigbox but below are some direct links:

  1. Introducing signals and demonstrating each signals method
  2. Explanations of each expDef input and how to use them in your own expDef
  3. A demonstration of each visual stimulus function
dbirman commented 4 years ago

Thanks, I will take a look!