Back to Main Page

Introduction to PsychToolBox

Dr Lincoln Colling

ljc65@cam.ac.uk

http://pbs2.mindsci.net

Lecture 3


Recap of loops

The best way to understand loops is just to try out a few. Try out a few loops and see how the value of the iterated variable (i or t in the examples below) changes on each iteration.

for i = 1 : 10
    i
end
i = 0;
while i < 5
    i
    i = i + 1;
end
arrayfun(@(i) i, 1:10)
arrayfun(@(i,t) [i;t], 1:10,2:11,'UniformOutput',false)

PsychToolBox

  • A set of matlab functions originally used for visual psychophysics research
  • Brainard, D. H. (1997) The Psychophysics Toolbox, Spatial Vision, 10, 433–436.

Installing PTB

  • There are instructions for how to install PTB on the PTB website
  • But I’ve written a little function that will install it for you

The Screen function


Displaying stimuli with PTB

  • Presenting stimuli with PTB involves two steps
    1. In the first step you construct your stimulus is a hidden buffer
    2. In the second step you Flip the screen to display the hidden buffer
  • This allows you to construct visual stimuli that are made up of several parts but to precisely display all the parts simultaneously
  • This is import if we want to be able accurately measure the difference in time between, for example, the presentation of the stimulus and the time of a button press (i.e., a reaction time).

The Screen coordinate system

How coordinates are specific on the screen


The PsychToolBox Screen buffer system

How the double screen buffer in PTB works


The OpenWindow command

`matlab [windowPtr,rect]=Screen('OpenWindow',windowPtrOrScreenNumber [,color] [,rect]); ##### The inputs:

  • windowPtrOrScreenNumber determine which monitor to open the screen on, e.g., 0 is the main monitor (this is only important for multi-monitor setups)
  • color sets the windows background colour. The default is white, but often you’ll want black or a mid grey colour
  • rect sets the window size. The default is the full screen

The outputs:
  • windowPtr tells you what screen you opened. You can use this with later commands to make sure you draw stimuli to the same screen you opened
  • rect tells you the size of the screen you opened. You can use this with later commands to make sure you place stimuli with the correct coordinates

If you need to get help on the OpenWindow command you can type Screen OpenWindow? at the matlab command line

>> Screen OpenWindow?

Note: If you’re using multiple monitor and you want to get the screen numbers for the various montiors then you can use Screen('Screens') and PTB will output the screen indexes.


Determining the screen size

PTB has a number of help commands that can help you determine the size of the screen

[width, height]=Screen('WindowSize', windowPointerOrScreenNumber)
  • The width and height of the screen in pixels
[x,y] = RectCenter(rect)
  • The x and y coordinates closet to the centre of the screen

Drawing shapes

  • PTB provides many ways to draw stimuli, including drawing lines, boxes and circle
    • Screen('FillRect',windowPtr,color,rect)
    • Screen('FrameRect',windowPtr,color,rect,'penWidth')
    • Screen('FillOval',windowPtr,color,rect)
% open a 800 x 600 px PTB window and draw a 100 x 100 px black rectangle in the middle of the screen
[windowPtr,rect]=Screen('OpenWindow',0, [],[0 0 800 600])
[x,y] = RectCenter(rect)
Screen('FillRect',windowPtr, [0 0 0], [x-50 y-50 x+50 y+50])
Screen('Flip',windowPtr)

Drawing lines

  • In addition to drawing shapes, PTB can also draw lines

    Screen('DrawLine', windowPtr [,color], fromH, fromV, toH, toV [,penWidth]
  • Draws a line from (fromH,fromV) to (toH,toV) that is penWidth thick


Shapes demo

Note: In PTB you can layer shapes on top of each other. You can use this to build up complex images piece by piece. There are many other drawing commands such as DrawDots, and DrawLines. You can explore them all by reading through the PTB manual or my exploring Peter Scarfe’s PTB demo site


Drawing text

Writing text to the screen with PTB requires a couple of steps

  1. Set the text attributes
    1. TextSize: How big is it
    2. TextFont: What font is it
    3. TextStyle: Is is bold, italics etc
  2. Draw the text with Screen('DrawText',...) or DrawFormattedText()
    1. DrawFormattedText() allows for line breaking etc so it’s good for presenting instructions, but if we’re just presenting text stimuli then Screen('DrawText',...)

Screen('DrawText',...)

The DrawText command takes a number of options

[newX,newY,textHeight]=Screen('DrawText', windowPtr, text [,x] [,y] ...
 [,color] [,backgroundColor] [,yPositionIsBaseline] [,swapTextDirection]);
  • text is the text you want to display
  • x & y are the coordinates for where the pen starts drawing
  • the remaining options allow you to set the colour, the background colour, whether to start at the top or bottom of text, and the writing direction.

DrawFormattedText()

The DrawFormattedText() function also takes a number of options

[nx, ny, textbounds, wordbounds] = DrawFormattedText(windowPtr, text [, sx][, sy] ...
[, color][, wrapat][, flipHorizontal][, flipVertical][, vSpacing] ... 
[, righttoleft][, winRect])
  • Unlike ScreenScreen('DrawText',...), DrawFormattedText() allows you to specific the start of an invisible bounding box around the text (rather than the pen start position) with sx and sy
  • You can also centre the text on the screen by setting sx = 'center' and sy = 'center'
  • wrapat specifics how many characters per line you wrap the text at if you’re presented long strings of text

A DrawText example

[w,rect] = OpenPTBWindow()
[xCenter,yCenter] = RectCenter(rect); % get the centre coordinates
Screen('TextSize',w,50) % Set text size to 50
Screen('TextStyle',w,1) % Set the text to BOLD
Screen('DrawText',w,'Hello Human!',xCenter,yCenter) % draw the text


A DrawFormattedText() example

[w,rect] = Screen('OpenWindow',0); % open a window
[xCenter,yCenter] = RectCenter(rect); % get the centre coordinates
Screen('TextSize',w,50) % Set text size to 50
Screen('TextStyle',w,1) % Set the text to BOLD
DrawFormattedText(w,'Hello Human!','center','center')


wrapat at work


Collecting responses

  • PTB can interact with many different types of devices to collect responses include keyboard, mouse, and specialised button boxes
  • And PTB can collect responses in a few different ways, depending on your needs (Ease of use vs timing accuracy)

Listing available devices

  • The PsychHID() function provides a method for interacting with Human Interface Devices such as keyboard, mice, etc

  • Before you can collect responses from e.g., a keyboard you’ll need to know it’s device number. There are a couple of ways to do this

% returns a structure of all the available HIDs
devices = PsychHID('Devices') 

% returns the indices and names of all the keyboards
[deviceIndices, deviceNames] = GetKeyboardIndices  
  • If you plug in and out keyboards and mice then the device indices can change, so make sure you double check before starting an experiment!

Collecting keyboard responses

PTB provides a number of functions for collecting keyboard responses. These include:

  • GetChar(): Get presses that are in the buffer (almost never used, so we won’t discuss it)
  • KbWait(): Pauses until a key is pressed (good for instruction screens)
  • KbCheck(): Check to see whether a key has been pressed
  • KbQueueCheck(): An alternative to KbCheck() which provides very accurate timing

In our practicals we’ll mainly be using KbWait() and KbQueueCheck(), so we’ll cover these in more detail.


The KbWait() function

[secs, keyCode, deltaSecs] = KbWait([deviceNumber][, forWhat=0][, untilTime=inf])
  • deviceNumber is the device that we want to use
  • forWhat: 0 when the key is pressed, 1 when the key is released, 2 waits until all the keys are released and then when a key is pressed, and 3 waits until all the key are released and when a key is pressed and released.
  • untilTime: how long to wait before moving on e.g., GetSecs() + 5 will wait 5 seconds and then move on
  • keyCode tells you the code of the pressed key KbName(keyCode), will tell you the name (e.g., 'space')

KbWait() example

[w,rect] = Screen('OpenWindow',0); % open a window
[xCenter,yCenter] = RectCenter(rect); % get the centre coordinates
Screen('TextSize',w,12) % Set text size to 12
Screen('TextStyle',w,1) % Set the text to BOLD
DrawFormattedText(w,'Press any key to continue','center','center')
Screen('Flip',w)
KbWait(-1)

Note: An alternative to using KbWait() is to use KbTriggerWait(). This allows you to specify which key to wait for. You have to specify the device and can’t just use -1 to listen to all devices. Eg., KbTriggerWait(KbName('space'), 4) waits until space has been pressed on device 4.


The KbQueueCheck function

The KbQueueCheck() function is used in combination with a number of other functions to create and check streams of keyboard responses

  • KbQueueCreate(): Create a keyboard queue
  • KbQueueStart(): Start recording key press
  • KbQueueStop(): Stop recording key presses
  • KbQueueCheck(): Check for key presses
  • KbQueueWait(): Wait for key presses
  • KbQueueFlush(): Flush the keyboard queue
  • KbQueueRelease(): Destroy the keyboard queue

Using KbQueue

% create a queue on DEVICE where keyList defines which keys to listen out for
KbQueueCreate(DEVICE,keyList); 

KbQueueStart(DEVICE); % start recording key presses

% get information about key presses
% if you want to end the trial when a key is pressed you'd put
% this command in a while loop and look while pressed == 0
% set pressed = 0 before the loop starts
[pressed, firstPress, firstRelease, lastPress, lastRelease] = KbQueueCheck(DEVICE); 

KbQueueFlush(DEVICE); % to empty the stream between trials

KbQueueStop(DEVICE); % to stop recording keypresses 
KbQueueRelease(DEVICE); % to destroy the stream when you're done

Reading events from KbQueueCheck()

[pressed, firstPress] = KbQueueCheck(DEVICE); 
  • pressed: outputs 1 if a key has been pressed, otherwise 0
  • firstPress: a 1 x 256 array that contains the time the key was pressed (each element corresponds to a particular key)
    • find(firstPress > 0) will find the keycode of the pressed key
    • KbName(find(firstPress > 0)) will tell you the name of the key pressed e.g., 'space'
    • firstPress(firstPress > 0) will tell you the time the key was pressed

Measuring reaction times

A common reason for using software like PTB is to measure reaction time i.e., the type between when a stimulus is shown and when a response is made

% draw a stimulus
Screen('FillRect',windowPtr, [0 0 0], [x-50 y-50 x+50 y+50])

% present the stimulus and record the time is was shown
stimOnset = Screen('Flip',windowPtr)

% collect some responses 
pressed = 0
while pressed = 0 % loop until a key press is detected
    [pressed, firstPress] = KbQueueCheck(DEVICE); 
end

% Calculate how quickly it took for the participant to press space
responseOnset = firstPress(KbName('space')) % get the press type for 'space'

reactionTime = responseOnset - stimOnset % different between stimOnset and responseOnset

Task for the practical

The task in the second practical will be to put all of this code together and to program up a real experiment. We are going to try to make an experiment similar to that used by Dehaene (1996).










Dehaene, S. (1996) The organisation of brain activations in number comparison: Event-related potentials and the additive factors methods, Journal of Cognitive Neuroscience, 8 (1), 47--68.