0

I am trying to create a simple RT experiment in MATLAB R2014b, using Psychtoolbox. Participants will have to categorize faces, pressing one of two buttons as fast as they can. I created the paradigm on one computer, and it is working fine on that, but when I moved it to another (the one I want to be testing on), there was a weird error: even though the program seemed to be logging keypresses on the majority of trials, sometimes it wouldn't respond, and I had to press the key a number of times before it proceeded to the next trial. I am unsure what's going in, but I assume there could be something wrong with the computer itself (what might that be?), or with this particular bit of the code:

    Screen('Flip', mainwin);
    timeStart = GetSecs;keyIsDown=0; correct=0; rt=0;
    while 1
        bf = 0; %this variable is irrelevant here, I use it later to break 
        out of a loop 
        while (GetSecs - timeStart) < 0.2 %faces are presented briefly, but 
        %I'm recording responses here anyway, just in case there are some 
        %fast anticipatory responses - after this loop is over, I keep 
        %recording RT and button press the exact same way, but with no 
        %stimulus present
            [keyIsDown, secs, keyCode] = KbCheck;
            FlushEvents('keyDown');
            if keyIsDown
                nKeys = sum(keyCode);
                if nKeys==1
                    if keyCode(Key1)||keyCode(Key2)
                        rt = 1000.*(GetSecs-timeStart);
                        keypressed=find(keyCode);
                        Screen('Flip', mainwin);
                        type = 'T';
                        bf = 1;
                        if keyCode(Key1) & targ_pic == 1
                            correct = 1;
                        elseif keyCode(Key2) & targ_pic == 0
                            correct = 1;
                        end
                        break;
                    elseif keyCode(escKey)
                        ShowCursor; fclose(outfile);  Screen('CloseAll'); 
                        return
                    end
                    keyIsDown=0; keyCode=0;
                end
            else
                keypressed = 0; 
            end
        end

Can anyone maybe spot something that may be wrong with this?

Incidentally: is this the correct way to get RT out of PTB? I found that bit of code online, but I'm a little uncertain about why the "secs" variable is not used.

Both computers run Windows 10.

MGy
  • 25
  • 1
  • 7

1 Answers1

1

A few suggestions:

The Flip command will return the estimate of stimulus onset time, currently you are calling GetSecs after the Flip command, which is not necessary and will always return a value that is slightly later than the actual screen Flip. Likewise, you can use the time of key press returned by KbCheck, rather than calling GetSecs after identifying a key press.

I don't think you need the FlushEvents command, and it might be causing some timing variability.

It is also sometimes useful to pause for a short amount of time (for example 1 millisecond) between KbCheck events.

Below is a version of your code snippet with a few of these changes. It may also be more concise to have a single response checking loop, in which you Flip off the stimulus after 200 ms, rather than separate pre 200 ms and post 200 ms response checking loops, though I haven't made that change here.

keyIsDown=0; correct=0; rt=0;
[~, timeStart] = Screen('Flip', mainwin);
while 1
    bf = 0; %this variable is irrelevant here, I use it later to break
    %out of a loop
    while (GetSecs - timeStart) < 0.2 %faces are presented briefly, but
        %I'm recording responses here anyway, just in case there are some
        %fast anticipatory responses - after this loop is over, I keep
        %recording RT and button press the exact same way, but with no
        %stimulus present
        [keyIsDown, secs, keyCode] = KbCheck;
        if keyIsDown
            nKeys = sum(keyCode);
            if nKeys==1
                if keyCode(Key1)||keyCode(Key2)
                    rt = 1000.*(secs-timeStart);
                    keypressed=find(keyCode);
                    Screen('Flip', mainwin);
                    type = 'T';
                    bf = 1;
                    if keyCode(Key1) & targ_pic == 1
                        correct = 1;
                    elseif keyCode(Key2) & targ_pic == 0
                        correct = 1;
                    end
                    break;
                elseif keyCode(escKey)
                    ShowCursor; fclose(outfile);  Screen('CloseAll');
                    return
                end
                keyIsDown=0; keyCode=0;
            end
        else
            keypressed = 0;
        end
        WaitSecs(.001);
    end
end
DMR
  • 1,479
  • 1
  • 8
  • 11
  • Thank you, these are very useful comments. Do you think that one of these issues may be behind KbCheck not registering keypresses on some trials? (Unfortunately I am unable to check right now if that issue is resolved this way on that computer.) Furthermore, I wanted to make it more concise and have just one checking loop with the stimulus disappearing after 200 ms, but couldn't figure out a way. Doing it this way, with two consecutive loops is wrong (i.e., might return largely - +/- more than 20 ms? - incorrect RT estimates), or just not elegant? – MGy May 13 '17 at 23:51
  • I think the changes may fix the KbCheck not registering issue, but I'm not 100% sure. On using one RT loop vs. two, two loops isn't wrong, and shouldn't add error to the response times, but is just more complicated because you're including the RT check code twice. To use one loop you would just keep checking RT until the response period has elapsed (instead of checking until 200 ms have elapsed). Then, within that main loop, also check to see whether 200 ms have elapsed, and whether the stimulus is still on screen. If so, Flip the stimulus off. – DMR May 14 '17 at 22:24