What is Matlab Psychtoolbox, and how can I learn it?

Matlab is useful for many things as a stand alone program, such as any math or computationally intensive tasks, and is particularly well suited for working with matrices. Matlab can also read in most brain data formats, so that you can do lots of fancy stuff with your brain data. Matlab can be obtained free of charge for the FAS website. However, if you want to use it for stimulus presentation with the help of Psychtoolbox, then you need a version of Matlab that can be run in 32bit mode, the latest being 2009b. The FAS IT (ithelp [at] harvard [dot] edu) people can help you get this going on your computer, as it is not as simple as the regular download. Psychtoolbox is a toolbox created for Matlab that makes presenting stimuli and collecting behavioral responses easier. As far as learning these programs, I suggest some slides made up by a friend of mine, Dr. Keith Schneider, a true matlab guru. Once you go over these on your own and play around some, if you have some questions or would like further help, you can contact Stephanie (smcmains [at] fas [dot] harvard [dot] edu).

How can I automatically determine the device number for the trigger/button box?

While the device number corresponding to the signals from the scanner can vary depending on what you have connected and in what order you connected things, the device name is always the same. Therefore, you can use this to determine the device number:

deviceString='Serial+Keyboard+Mouse+Joystick';%% name of the scanner trigger box

If you are using the new fiber optic response boxes, the device name will be: deviceString='Celeritas Dev';

[id,name] = GetKeyboardIndices;% get a list of all devices connected

device=0;

for i=1:length(name)%for each possible device

if strcmp(name{i},deviceString)%compare the name to the name you want

device=id(i);%grab the correct id, and exit loop

break;

end

end

if device==0%%error checking

error(‘No device by that name was detected’);

end

You can do the same thing with your internal keyboard for when you run the experiment outside of the scanner.

For my mac, this is called: 'Apple Internal Keyboard / Trackpad’. To find out what yours is called, from the Matlab command window:

[id,name] = GetKeyboardIndices

This should print out a list of IDs and names. If the names come up as something like [1x34 char] because they are cell arrays, you can see them by typing: name{:}

What is the best way to ensure I don’t miss any button box responses at the scanner?

The best way to do this is to use the set of commands that involve KbQueueCheck. For a summary of the reasoning behind this, see here, and the psychtoolbox doc about it here. The idea is that all keyboard presses will be put into a queue, as opposed to KbCheck which asks if a key is pressed at the very moment you call it. KBQueueCheck will only log key presses from one device at any given time, so you must give it a device number (see here for how to get this number). You can also give it a list of keys to look for, so that you can look for just a subset of keys. This can be handy if you don’t want your subjects to accidentally trigger your experiment. Before using KbQueueCheck you must first setup the internal queue. This is done via KbQueueCreate, which takes the device number and list of keys to check. Once set up, a queue can be used multiple times, as long as the device and keys of interest don’t change. To change to a different keyboard or set of keys, simply call KbQueueCreate again with the new specification. It is not necessary to call KbQueueRelease (or ‘clear mex’) before a second call to KbQueueCreate, but it should be called when it is no longer needed to release resources. Since creation of a queue involves some computational overhead, delivery of keyboard events to the queue is not started automatically. This allows the queue to be created in advance during a phase that is not time critical and then subsequently efficiently started in a phase that is potentially time critical. Delivery of events to the queue is started by a call to KbQueueStart. Delivery can subsequently be stopped (without losing any queued events that have not yet been retrieved) by a call toKbQueueStop. Events can be retrieved by calling KbQueueCheck, which will report about new events since the most recent call to KbQueueStart, KbQueueCheck, KbQueueFlush or KbQueueWait. Although a call to KbQueueStart should suffice to flush a queue that is not actively receiving events, KbQueueFlush should be used preferentially to flush events from an actively running queue. Analogously to KbWait, the function KbQueueWait can be used to pause execution until a keypress has taken place (and unlike KbWait, will respond to very brief events like from our scanner). Like KbWait, KbQueueWait does not directly identify the specific key that was pressed, and it should be kept in mind that the keypress will already have been removed from the queue when KbQueueWait returns and its identity therefore cannot be recovered by an immediate call to KbQueueCheck. If the identity of the pressed key is needed, KbQueueCheck should be called directly in a tight loop instead of using KbQueueWait. If only one key is of interest, another option is to specify only that key when creating the queue with KbQueueCreate. Here is a more specific example:

keys=[30,31,32,33,46];%%all keys on right hand plus trigger, can be found by running kbdemo

keylist=zeros(1,256);%%create a list of 256 zeros

keylist(keys)=1;%%set keys you interested in to 1

3. Make queue

KbQueueCreate(device,keylist);%%make cue

4. Start queue: This can be done anytime, or right before you want to get responses.

KbQueueStart();%%start listening

5. If you started the queue early, or want to make sure you get the ‘next’ keypress, you can clear the queue:

KbQueueFlush();%%removes all keyboard presses

6. Get responses. This call gives you information about keypresses on the specified device since the most recent call to this routine, KbQueueStart, or KbQueueWait. This is an example of a loop to wait for the trigger:

pressed=0;

while ~pressed

[pressed, firstpress] = KbQueueCheck(); %check response

end

This loop will exit when a key is pressed. If you want it to only look for the trigger, only include the trigger code in your keylist. However, you will then have to recreate your queue to include the response buttons you want to get also. This can take a little bit of time so you should do it before you need it (like right after get trigger but before first trial starts). Also, this loop is looping over very little, so there is concern that the operating system will get unhappy at Matlab for sucking up all the processing and will demote the priority of the program. There are two ways to correct for this. The first is to include a waitsecs(.01) in the while loop, this helps keep the OS happy. Alternatively, you can set the priority of the program after the trigger is registered and the loop ends: Priority(MaxPriority(wp)).

7. Here is an example of how to get responses and RTs.

a. Display your stimulus

b. Get the current time: start_resp_time=GetSecs;

c. Clear the queue: KbQueueFlush();

d. Look for responses, this can be in the loop where you wait for the length of your stim, or maybe while you are presenting a movie or other stim.

[pressed, firstpress]=KbQueueCheck(); %check response

if firstpress(resp_key)>0%if hit response key

data(trial_num, 1)=GetSecs-start_resp_time;

end

Note: The key buffer can fill up, so if you aren’t going to be checking for responses very often, or you have a very short TR, you should edit the queue after you get the first trigger so that it will no longer register trigger responses.

How can I keep subjects from accidentally triggering my experiment?

KbQueue Method:

If you are using the KbQueueCheck method recommended here, you can create the queue to only look for the trigger. To do this, make your keylist contain all zeros except for the trigger:

keys=[46];%% trigger

keylist=zeros(1,256);%%create a list of 256 zeros

keylist(keys)=1;%%set keys you interested in to 1

Then, after you receive the trigger, you can change your queue to include just the buttons you want to look for.

KbCheck Method:

If you are using KbCheck you can disable certain keys, then KbCheck and KbWait will ignore them:

disablekeys=[39,30,31,32,33];%%all the keys on the right hand button box

olddisabledkeys = DisableKeysForKbCheck([disablekeys]);

Then afterwards you can reset to exclude nothing:

olddisabledkeys = DisableKeysForKbCheck([olddisabledkeys]);

Or to exclude the trigger

olddisabledkeys = DisableKeysForKbCheck([46])

Note: These settings are reset to all keys enabled with a call to ‘clear all’

How do I submit my matlab script to the NCF?

You can submit matlab to the cluster by using the –nodisplay and –r flags. For instance: bsub –q ncf matlab -nodisplay -r "addpath /ncf/apps/spm8; run_preproc_package('hcscore_cc.txt')"

After the required matlab flags, you can enclose several commands to execute at once by placing them in double quotes. Here I am adding spm to the matlab path (which you should do in your enivorment instead, as described here) and then running a script called run_preproc_package that takes one argument. If you just want to run a script you don't need the quotes.

I get an error message when I try and save my path in matlab.

This is usually because it wants to save it in a default location you don't have write access to. Instead, save it in your own user's directory: