Psychtoolbox
For most experiments we don’t want to use the Matlab figure window
or command window for input or display, since that is pretty slow
and clunky.
So we are going to start using a group of Matlab programs developed
especially for doing behavioral experiments. Many groups have
developed similar sets of programs: the particular ones we are
going to use are called PsychToolbox.
What is Psychtoolbox?
Psychtoolbox is a free set of MATLAB functions which help
researchers carry out vision research on Macintosh and Windows
computers. It is a collection of matlab functions mainly written to
make presenting visual stimuli easier.It was written by David
Brainard, Denis Pelli, Mario Kleiner and Allen Ingling.
The current version of Psychtoolbox is based on OpenGL commands. At
its most basic level OpenGL is simply a document that describes a
set of functions and the precise behaviours that they must
perform.
One of the important things about OpenGL is that functions are
supposed to work across platforms. From this specification,
hardware and software vendors create implementations — libraries of
functions created to match the functions stated in the OpenGL
specification. Vendors have to meet specific tests to be able to
qualify their implementation as an OpenGL implementation. OpenGL is
also used in CAD, virtual reality, scientific visualization,
information visualization, and flight simulation, as well as (of
course) video games.
This is meant to mean that Psychtoolbox works similarly in PCs as
in Macs. Sadly this isn't always the case, but in most cases the
same Matlab scripts will work on PCs and Macs with little or no
modification.
Downloading Psychtoolbox
You need to download PsychToolbox from here:
http://psychtoolbox.org/
Follow the instructions very carefully and accurately, it’s a
fiddly process.
Once you have installed PsychToolbox, then you can carry on with
this chapter.
Citing Psychtoolbox
Remember to cite the Toolbox. Citing the toolbox isn't just the
right thing to do - it's a way of demonstrating that the toolbox is
useful so that agencies like the NIH will keep funding it.
"We wrote our experiments in MATLAB, using the Psychophysics
Toolbox extensions (Brainard, 1997; Pelli, 1997)."
Brainard, D. H. (1997) The Psychophysics Toolbox, Spatial Vision
, 10:443-446. Pelli, D. G. (1997) The VideoToolbox software for
visual psychophysics: Transforming numbers into movies, Spatial
Vision 10:437-442.
Getting started with PsychToolbox Screen.m
Start with just 1 monitor
Try typing the following into the command window:
***** ScreenTest: Testing Screen 0
*****
PTB-INFO: This is the OpenGL-Psychtoolbox for
Microsoft Windows, version 3.0.8. (Build date: Aug 15
2008)
PTB-INFO: Type 'PsychtoolboxVersion' for more
detailed version information.
PTB-INFO: Psychtoolbox is licensed to you under
terms of the GNU General Public License (GPL). See file
'License.txt' in the
PTB-INFO: Psychtoolbox root folder for a copy of
the GPL license.
OpenGL-Extensions are: GL_EXT_blend_minmax
GL_EXT_blend_subtract GL_EXT_blend_color GL_EXT_abgr
GL_EXT_texture3D GL_EXT_clip_volume_hint
GL_EXT_compiled_vertex_array GL_SGIS_texture_edge_clamp
GL_SGIS_generate_mipmap GL_EXT_draw_range_elements
GL_SGIS_texture_lod GL_EXT_rescale_normal GL_EXT_packed_pixels
GL_EXT_separate_specular_color GL_ARB_multitexture
GL_EXT_texture_env_combine GL_EXT_bgra GL_EXT_blend_func_separate
GL_EXT_secondary_color GL_EXT_fog_coord GL_EXT_texture_env_add
GL_ARB_texture_cube_map GL_ARB_transpose_matrix
GL_ARB_texture_env_add GL_IBM_texture_mirrored_repeat
GL_EXT_multi_draw_arrays GL_NV_blend_square
GL_ARB_texture_compression GL_3DFX_texture_compression_FXT1
GL_EXT_texture_filter_anisotropic GL_ARB_texture_border_clamp
GL_ARB_point_parameters GL_ARB_texture_env_combine
GL_ARB_texture_env_dot3 GL_ARB_texture_env_crossbar
GL_EXT_texture_compression_s3tc GL_ARB_shadow GL_ARB_window_pos
GL_EXT_shadow_funcs GL_EXT_stencil_wrap GL_ARB_vertex_program
GL_EXT_texture_rectangle GL_ARB_fragment_program
GL_EXT_stencil_two_side GL_ATI_separate_stencil
GL_ARB_vertex_buffer_object GL_EXT_texture_lod_bias
GL_ARB_occlusion_query GL_ARB_fragment_shader GL_ARB_shader_objects
GL_ARB_shading_language_100 GL_ARB_texture_non_power_of_two
GL_ARB_vertex_shader GL_NV_texgen_reflection GL_ARB_point_sprite
GL_EXT_blend_equation_separate GL_ARB_depth_texture
GL_ARB_texture_rectangle GL_ARB_draw_buffers
GL_ARB_pixel_buffer_object GL_WIN_swap_hint
GL_EXT_framebuffer_object
PTB-INFO: OpenGL-Renderer is Intel :: Intel
Cantiga :: 2.0.0 - Build 7.15.10.4977
PTB-Info: VBL startline = 800 , VBL Endline =
822
PTB-Info: Measured monitor refresh interval from
beamposition = 16.656752 ms [60.035716 Hz].
PTB-Info: Will use beamposition query for
accurate Flip time stamping.
PTB-Info: Measured monitor refresh interval from
VBLsync = 16.656703 ms [60.035889 Hz]. (112 valid samples taken,
stddev=0.199544 ms.)
PTB-Info: Reported monitor refresh interval from
operating system = 16.666667 ms [60.000000 Hz].
PTB-Info: Small deviations between reported
values are normal and no reason to worry.
PTB-INFO: Using OpenGL GL_TEXTURE_RECTANGLE_EXT
extension for efficient high-performance texture
mapping...
***** ScreenTest: Done With Screen 0
*****
If you get the screen going blank and then something like the above
then screenTest worked.
If not, then Psychtoolbox isn't working right on your computer. The
notes that are spat out of screentest may
help you work out what's wrong. If not, contact Geoff or
myself.
Writing code using Screen.m
The next stage is also very simple. We are simply going to open an
experimental window which will start out being white, we will then
make it black and then close it again.
The script below uses a command called Screen, which is one of the
core functions of PsychToolbox. Screen is actually not an m file
(like the ones you have been writing till now). It is a mex file.
This means that it is written in C using OpenGL, and is then
compiled to run in Matlab. The reason this was done is because
Screen does some pretty funky stuff that would be impossible in
Matlab.
FlipScreen.m
%
% opens a window using Psychtoolbox,
% makes the window black, then white, and then
closes
% the window again
%
% written for Psychtoolbox 3 on the PC by IF
3/2007
clear all
screens=0;
[wPtr,rect]=Screen('OpenWindow',screens, 0, []);
HideCursor;
tic
while toc<2
end
Screen('Close', wPtr);
PTB-INFO: This is the OpenGL-Psychtoolbox for
Microsoft Windows, version 3.0.8. (Build date: Aug 15
2008)
PTB-INFO: Type 'PsychtoolboxVersion' for more
detailed version information.
PTB-INFO: Psychtoolbox is licensed to you under
terms of the GNU General Public License (GPL). See file
'License.txt' in the
PTB-INFO: Psychtoolbox root folder for a copy of
the GPL license.
OpenGL-Extensions are: GL_EXT_blend_minmax
GL_EXT_blend_subtract GL_EXT_blend_color GL_EXT_abgr
GL_EXT_texture3D GL_EXT_clip_volume_hint
GL_EXT_compiled_vertex_array GL_SGIS_texture_edge_clamp
GL_SGIS_generate_mipmap GL_EXT_draw_range_elements
GL_SGIS_texture_lod GL_EXT_rescale_normal GL_EXT_packed_pixels
GL_EXT_separate_specular_color GL_ARB_multitexture
GL_EXT_texture_env_combine GL_EXT_bgra GL_EXT_blend_func_separate
GL_EXT_secondary_color GL_EXT_fog_coord GL_EXT_texture_env_add
GL_ARB_texture_cube_map GL_ARB_transpose_matrix
GL_ARB_texture_env_add GL_IBM_texture_mirrored_repeat
GL_EXT_multi_draw_arrays GL_NV_blend_square
GL_ARB_texture_compression GL_3DFX_texture_compression_FXT1
GL_EXT_texture_filter_anisotropic GL_ARB_texture_border_clamp
GL_ARB_point_parameters GL_ARB_texture_env_combine
GL_ARB_texture_env_dot3 GL_ARB_texture_env_crossbar
GL_EXT_texture_compression_s3tc GL_ARB_shadow GL_ARB_window_pos
GL_EXT_shadow_funcs GL_EXT_stencil_wrap GL_ARB_vertex_program
GL_EXT_texture_rectangle GL_ARB_fragment_program
GL_EXT_stencil_two_side GL_ATI_separate_stencil
GL_ARB_vertex_buffer_object GL_EXT_texture_lod_bias
GL_ARB_occlusion_query GL_ARB_fragment_shader GL_ARB_shader_objects
GL_ARB_shading_language_100 GL_ARB_texture_non_power_of_two
GL_ARB_vertex_shader GL_NV_texgen_reflection GL_ARB_point_sprite
GL_EXT_blend_equation_separate GL_ARB_depth_texture
GL_ARB_texture_rectangle GL_ARB_draw_buffers
GL_ARB_pixel_buffer_object GL_WIN_swap_hint
GL_EXT_framebuffer_object
PTB-INFO: OpenGL-Renderer is Intel :: Intel
Cantiga :: 2.0.0 - Build 7.15.10.4977
PTB-Info: VBL startline = 800 , VBL Endline =
822
PTB-Info: Measured monitor refresh interval from
beamposition = 16.656780 ms [60.035613 Hz].
PTB-Info: Will use beamposition query for
accurate Flip time stamping.
PTB-Info: Measured monitor refresh interval from
VBLsync = 16.656737 ms [60.035768 Hz]. (50 valid samples taken,
stddev=0.001461 ms.)
PTB-Info: Reported monitor refresh interval from
operating system = 16.666667 ms [60.000000 Hz].
PTB-Info: Small deviations between reported
values are normal and no reason to worry.
PTB-INFO: Using OpenGL GL_TEXTURE_RECTANGLE_EXT
extension for efficient high-performance texture
mapping...
help with Screen
There are two ways of getting help with Screen If you type:
You get some general information about Screen
If you type:
% Activate compatibility mode: Try to behave
like the old MacOS-9 Psychtoolbox:
oldEnableFlag=Screen('Preference',
'EmulateOldPTB', [enableFlag]);
% Open or close a window or
texture:
[windowPtr,rect]=Screen('OpenWindow',windowPtrOrScreenNumber
[,color] [,rect] [,pixelSize] [,numberOfBuffers] [,stereomode]
[,multisample][,imagingmode]);
[windowPtr,rect]=Screen('OpenOffscreenWindow',windowPtrOrScreenNumber
[,color] [,rect] [,pixelSize] [,specialFlags]
[,multiSample]);
textureIndex=Screen('MakeTexture', WindowIndex,
imageMatrix [, optimizeForDrawAngle=0] [, specialFlags=0] [,
floatprecision=0] [, textureOrientation=0] [,
textureShader=0]);
Screen('Close', [windowOrTextureIndex or list of
textureIndices/offscreenWindowIndices]);
Screen('CloseAll');
% Draw lines
and solids like QuickDraw and DirectX (OS 9 and
Windows):
currentbuffer = Screen('SelectStereoDrawBuffer',
windowPtr [, bufferid] [, param1]);
Screen('DrawLine', windowPtr [,color], fromH,
fromV, toH, toV [,penWidth]);
Screen('DrawArc',windowPtr,[color],[rect],startAngle,arcAngle)
Screen('FrameArc',windowPtr,[color],[rect],startAngle,arcAngle[,penWidth]
[,penHeight] [,penMode])
Screen('FillArc',windowPtr,[color],[rect],startAngle,arcAngle)
Screen('FillRect', windowPtr [,color] [,rect]
);
Screen('FrameRect', windowPtr [,color] [,rect]
[,penWidth]);
Screen('FillOval', windowPtr [,color]
[,rect]);
Screen('FrameOval', windowPtr [,color] [,rect]
[,penWidth] [,penHeight] [,penMode]);
Screen('FramePoly', windowPtr [,color],
pointList [,penWidth]);
Screen('FillPoly', windowPtr [,color],
pointList);
% New OpenGL functions for OS
X:
Screen('glPoint', windowPtr, color, x, y
[,size]);
Screen('gluDisk', windowPtr, color, x, y
[,size]);
Screen('DrawDots', windowPtr, xy [,size]
[,color] [,center] [,dot_type]);
Screen('DrawLines', windowPtr, xy [,width]
[,colors] [,center] [,smooth]);
[sourceFactorOld, destinationFactorOld,
colorMaskOld]=('BlendFunction', windowIndex, [sourceFactorNew],
[destinationFactorNew], [colorMaskNew]);
% Draw Text in windows
textModes =
Screen('TextModes');
oldCopyMode=Screen('TextMode', windowPtr
[,textMode]);
oldTextSize=Screen('TextSize', windowPtr
[,textSize]);
oldStyle=Screen('TextStyle', windowPtr
[,style]);
[oldFontName,oldFontNumber]=Screen(windowPtr,'TextFont'
[,fontNameOrNumber]);
[normBoundsRect,
offsetBoundsRect]=Screen('TextBounds', windowPtr,
text);
[newX,newY]=Screen('DrawText', windowPtr, text
[,x] [,y] [,color] [,backgroundColor]
[,yPositionIsBaseline]);
oldTextColor=Screen('TextColor', windowPtr
[,colorVector]);
oldTextBackgroundColor=Screen('TextBackgroundColor',
windowPtr [,colorVector]);
% Copy an image, very quickly, between textures,
offscreen windows and onscreen windows.
[resident [texidresident]] =
Screen('PreloadTextures', windowPtr [, texids]);
Screen('DrawTexture', windowPointer,
texturePointer [,sourceRect] [,destinationRect] [,rotationAngle] [,
filterMode] [, globalAlpha] [, modulateColor] [, textureShader] [,
specialFlags] [, auxParameters]);
Screen('DrawTextures', windowPointer,
texturePointer(s) [, sourceRect(s)] [, destinationRect(s)] [,
rotationAngle(s)] [, filterMode(s)] [, globalAlpha(s)] [,
modulateColor(s)] [, textureShader] [, specialFlags] [,
auxParameters]);
Screen('CopyWindow', srcWindowPtr, dstWindowPtr,
[srcRect], [dstRect], [copyMode])
% Copy an image, slowly, between matrices and
windows :
imageArray=Screen('GetImage', windowPtr [,rect]
[,bufferName] [,floatprecision=0]
[,nrchannels=3])
Screen('PutImage', windowPtr, imageArray
[,rect]);
% Synchronize with the window's screen
(on-screen only):
[VBLTimestamp StimulusOnsetTime FlipTimestamp
Missed Beampos] = Screen('Flip', windowPtr [, when] [, dontclear]
[, dontsync] [, multiflip]);
Screen('AsyncFlipBegin', windowPtr [, when] [,
dontclear] [, dontsync] [, multiflip]);
[VBLTimestamp StimulusOnsetTime FlipTimestamp
Missed Beampos] = Screen('AsyncFlipEnd',
windowPtr);
[VBLTimestamp StimulusOnsetTime FlipTimestamp
Missed Beampos] = Screen('AsyncFlipCheckEnd',
windowPtr);
[VBLTimestamp StimulusOnsetTime swapCertainTime]
= Screen('WaitUntilAsyncFlipCertain', windowPtr);
[telapsed] = Screen('DrawingFinished', windowPtr
[, dontclear] [, sync]);
framesSinceLastWait = Screen('WaitBlanking',
windowPtr [, waitFrames]);
% Load color lookup table of the window's screen
(on-screen only):
[gammatable, dacbits, reallutsize] =
Screen('ReadNormalizedGammaTable',
windowPtrOrScreenNumber);
Screen('LoadNormalizedGammaTable',
windowPtrOrScreenNumber, table [, loadOnNextFlip] [,
physicalDisplay]);
oldclut = Screen('LoadCLUT',
windowPtrOrScreenNumber [, clut] [, startEntry=0] [,
bits=8]);
% Get (and set) information about a window or
screen:
screenNumbers=Screen('Screens' [,
physicalDisplays]);
windowPtrs=Screen('Windows');
kind=Screen(windowPtr,
'WindowKind');
isOffscreen=Screen(windowPtr,'IsOffscreen');
hz=Screen('FrameRate', windowPtrOrScreenNumber
[, mode] [, reqFrameRate]);
hz=Screen('NominalFrameRate',
windowPtrOrScreenNumber [, mode] [,
reqFrameRate]);
[ monitorFlipInterval nrValidSamples stddev
]=Screen('GetFlipInterval', windowPtr [, nrSamples] [, stddev] [,
timeout]);
screenNumber=Screen('WindowScreenNumber',
windowPtr);
rect=Screen('Rect',
windowPtrOrScreenNumber);
pixelSize=Screen('PixelSize',
windowPtrOrScreenNumber);
pixelSizes=Screen('PixelSizes',
windowPtrOrScreenNumber);
[width, height]=Screen('WindowSize',
windowPointerOrScreenNumber);
[width, height]=Screen('DisplaySize',
ScreenNumber);
[oldmaximumvalue oldclampcolors] =
Screen('ColorRange', windowPtr [, maximumvalue][,
clampcolors=1]);
info = Screen('GetWindowInfo', windowPtr [,
beamposOnly=0]);
resolutions=Screen('Resolutions',
screenNumber);
oldResolution=Screen('Resolution', screenNumber
[, newwidth] [, newheight] [, newHz] [, newPixelSize] [,
specialMode]);
% Get/set details of environment, computer, and
video card (i.e. screen):
struct=Screen('Version');
comp=Screen('Computer');
oldBool=Screen('Preference', 'IgnoreCase'
[,bool]);
tick0Secs=Screen('Preference', 'Tick0Secs',
tick0Secs);
psychTableVersion=Screen('Preference',
'PsychTableVersion');
mexFunctionName=Screen('Preference',
'PsychTableCreator');
proc=Screen('Preference',
'Process');
Screen('Preference','SkipSyncTests',
skipTest);
Screen('Preference','VisualDebugLevel', level
(valid values between 0 and 5));
Screen('Preference', 'ConserveVRAM', mode (valid
values between 0 and 3));
Screen('Preference', 'Enable3DGraphics',
[enableFlag]);
% Helper
functions. Don't call these
directly, use eponymous wrappers:
[x, y, buttonVector]= Screen('GetMouseHelper',
numButtons);
Screen('HideCursorHelper',
windowPntr);
Screen('ShowCursorHelper',
windowPntr);
Screen('SetMouseHelper',
windowPntrOrScreenNumber, x, y);
% Internal testing of Screen
timeList=
Screen('GetTimelist');
Screen('ClearTimelist');
Screen('Preference','DebugMakeTexture',
enableDebugging);
% Movie and multimedia playback
functions:
[ moviePtr [duration] [fps] [width] [height]
[count]]=Screen('OpenMovie', windowPtr, moviefile [, async=0] [,
preloadSecs=1]);
Screen('CloseMovie',
moviePtr);
[ texturePtr
[timeindex]]=Screen('GetMovieImage', windowPtr, moviePtr,
[waitForImage], [fortimeindex], [specialFlags = 0] [, specialFlags2
= 0]);
[droppedframes] = Screen('PlayMovie', moviePtr,
rate, [loop], [soundvolume]);
timeindex = Screen('GetMovieTimeIndex',
moviePtr);
[oldtimeindex] = Screen('SetMovieTimeIndex',
moviePtr, timeindex);
% Video capture functions:
videoPtr =Screen('OpenVideoCapture', windowPtr
[, deviceIndex] [,roirectangle] [, pixeldepth] [, numbuffers] [,
allowfallback] [, targetmoviename] [, recordingflags] [,
captureEngineType]);
Screen('CloseVideoCapture',
capturePtr);
[fps starttime] = Screen('StartVideoCapture',
capturePtr [, captureRateFPS] [, dropframes=0] [,
startAt]);
droppedframes = Screen('StopVideoCapture',
capturePtr);
[ texturePtr [capturetimestamp] [droppedcount]
[summed_intensityOrRawImageMatrix]]=Screen('GetCapturedImage',
windowPtr, capturePtr [, waitForImage=1] [,oldTexture]
[,specialmode] [,targetmemptr]);
oldvalue = Screen('SetVideoCaptureParameter',
capturePtr, 'parameterName' [, value]);
% Low level direct access to OpenGL-API
functions:
% Online info for each function available by
opening a terminal window
% and typing 'man Functionname' +
Enter.
Screen('glPushMatrix',
windowPtr);
Screen('glPopMatrix',
windowPtr);
Screen('glLoadIdentity',
windowPtr);
Screen('glTranslate', windowPtr, tx, ty [,
tz]);
Screen('glScale', windowPtr, sx, sy [,
sz]);
Screen('glRotate', windowPtr, angle, [rx = 0],
[ry = 0] ,[rz = 1]);
% Support for 3D graphics rendering and for
interfacing with external OpenGL code:
Screen('Preference', 'Enable3DGraphics',
[enableFlag]); % Enable 3D gfx
support.
Screen('BeginOpenGL', windowPtr [,
sharecontext]); % Prepare window
for external OpenGL drawing.
Screen('EndOpenGL',
windowPtr); % Finish external
OpenGL drawing.
[targetwindow, IsOpenGLRendering] =
Screen('GetOpenGLDrawMode');
[textureHandle rect] =
Screen('SetOpenGLTextureFromMemPointer', windowPtr, textureHandle,
imagePtr, width, height, depth [, upsidedown][, target][,
glinternalformat][, gltype][, extdataformat]);
[textureHandle rect] =
Screen('SetOpenGLTexture', windowPtr, textureHandle, glTexid,
target [, glWidth] [, glHeight] [, glDepth] [,
textureShader]);
[ gltexid gltextarget texcoord_u texcoord_v ]
=Screen('GetOpenGLTexture', windowPtr, textureHandle [, x][,
y]);
% Support for plugins and for builtin high
performance image processing pipeline:
[ret1, ret2, ...] = Screen('HookFunction',
windowPtr, 'Subcommand', 'HookName', arg1, arg2,
...);
proxyPtr = Screen('OpenProxy', windowPtr [,
imagingmode]);
transtexid = Screen('TransformTexture',
sourceTexture, transformProxyPtr [, sourceTexture2][,
targetTexture][,
specialFlags]);
You get a list of all the subcommands that are
contained within Screen. To get more information about a particular
command type:
Usage:
[windowPtr,rect]=Screen('OpenWindow',windowPtrOrScreenNumber
[,color]
[,rect][,pixelSize][,numberOfBuffers][,stereomode][,multisample][,imagingmode]);
Open an onscreen window. Specify a screen by a
windowPtr or a screenNumber (0 is
the main screen, with menu bar). "color" is the
clut index (scalar or [r g b]
triplet) that you want to poke into each pixel;
default is white. If supplied,
"rect" must contain at least one pixel. If a
windowPtr is supplied then "rect"
is in the window's coordinates (origin at upper
left), and defaults to the whole
window. If a screenNumber is supplied then
"rect" is in screen coordinates
(origin at upper left), and defaults to the
whole screen. (In all cases,
subsequent references to this new window will
use its coordinates: origin at its
upper left.). Please note that while providing a
"rect" parameter to open a
normal window instead of a fullscreen window is
convenient for debugging, but
drawing performance, stimulus onset timing and
onset timestamping may be
impaired, so be careful.
"pixelSize" sets the depth (in bits) of each
pixel; default is to leave depth
unchanged. "numberOfBuffers" is the number of
buffers to use. Setting anything
else than 2 will be useful for
development/debugging of PTB itself but will mess
up any real experiment. "stereomode" Type of
stereo display algorithm to use: 0
(default) means: Monoscopic viewing. 1 means:
Stereo output via OpenGL on any
stereo hardware that is supported by MacOS-X,
e.g., the shutter glasses from
CrystalView. 2 means: Left view compressed into
top half, right view into bottom
half. 3 means left view compressed into bottom
half, right view compressed into
top half. 4 and 5 allow split screen display
where left view is shown in left
half, right view is shown in right half or the
display. A value of 5 does the
opposite (cross-fusion). Values of 6,7,8 and 9
enable Anaglyph stereo rendering
of types left=Red, right=Green, vice versa and
left=Red, right=Blue and vice
versa. A value of 10 enables multi-window
stereo: Open one window for left eye
view, one for right eye view, treat both of them
as one single stereo window.
See StereoDemo.m for examples of usage of the
different stereo modes. See
ImagingStereoDemo.m for more advanced usage on
modern hardware.
"multisample" This parameter, if provided and
set to a value greater than zero,
enables automatic hardware anti-aliasing of the
display: For each pixel,
'multisample' color samples are computed and
combined into a single output pixel
color. Higher numbers provide better quality but
consume more video memory and
lead to a reduction in framerate due to the
higher computational demand. The
maximum number of samples is hardware dependent.
Psychtoolbox will silently
clamp the number to the maximum supported by
your hardware if you ask for too
much. On very old hardware, the value will be
ignored. Read 'help AntiAliasing'
for more in-depth information about
multi-sampling. "imagingmode" This optional
parameter enables PTB's internal image
processing pipeline. The pipeline is off
by default. Read 'help PsychGLImageprocessing'
for information about this
feature.
Opening or closing a window takes about one to
three seconds, depending on type
of connected display. COMPATIBILITY TO OS-9 PTB:
If you absolutely need to run
old code for the old MacOS-9 or Windows
Psychtoolbox, you can switch into a
compatibility mode by adding the command
Screen('Preference', 'EmulateOldPTB',
1) at the very top of your script. This will
restore Offscreen windows and
WaitBlanking functionality, but at the same time
disable most of the new
features of the OpenGL Psychtoolbox. Please do
not write new experiment code in
the old style! Emulation mode is pretty new and
may contain significant bugs, so
use with great
caution!
Usage:
[newX,newY]=Screen('DrawText', windowPtr, text
[,x] [,y] [,color] [,backgroundColor]
[,yPositionIsBaseline]);
Draw text. On MS-Windows, "text" may include
two-byte (16 bit) Unicode
characters (e.g. Chinese). A standard
Matlab/Octave text string is interpreted
as 8 bit ASCII string. If you want to pass a
string which contains 16 bit UTF-16
unicode characters, convert the text to a double
matrix, ie, mytext =
double(myunicodetext); then pass the double
matrix to this function. Unicode
text drawing is supported if you select the
default high quality, but slower GDI
text renderer on Windows.
With the optional fast, low quality renderer,
neither anti-aliasing nor Unicode
are supported and text positioning may be a bit
less accurate, but it is a good
choice if you are in need for speed over
everything else. Select it via the
command:
Screen('Preference', 'TextRenderer', 0);
inserted at the top of your script.
On Linux, Unicode and anti-aliasing aren't
supported yet.
Default "x" "y" is current pen location. "color"
is the CLUT index (scalar or [r
g b] triplet) that you want to poke into each
pixel; default produces black with
the standard CLUT for this window's
pixelSize. "yPositionIsBaseline"
If
specified, will override the global preference
setting for text positioning: It
defaults to off. If it is set to 1, the y pen
location defines the base line of
drawn text, otherwise it defines the top of the
drawn text. Old PTB's had a
behaviour equivalent to setting 1, unfortunately
this behaviour wasn't
replicated in pre 3.0.8 PTB's so now we stick to
the new behaviour by default.
"newX, newY" return the final pen location. On
GNU/Linux the font renderer is
currently a very simple bitmap renderer which
doesn't allow for Unicode
rendering or anti-aliasing.Btw.:
Screen('Preference', ...); provides a couple of
interesting text preference settings that affect
text drawing, e.g., setting
alpha blending and anti-aliasing
modes.
Caveat
You should bear in mind that you are entering the murky world of
not-quite-professional code. Much of this code is written by people
like you, in the middle of trying to do real science. This means
that commands may not work as stated, help files may be out of
date, commands may not even exist.
Code comments for FlipScreen
screens=0;
[wPtr,rect]=Screen('OpenWindow',screens, 0, []);
Currently the command Screen is taking
two arguments.
The first argument is the text string 'OpenWindow' which
is telling Screen what you want it to do - open a window.
The second argument tells the command Screen which
computer monitor you want to use. If you are running more than one
monitor on your computer then 0 means the monitor with the menu
bar, 1 means any other monitor. For now, if you have any difficulty
I would make sure you are only using one monitor.
The third argument tells Screen that
you want the screen to be black (0 because screen uses a
zero-indexed colormap).
The fourth argument is a default, telling Matlab you want the
experimental screen to cover the entire monitor screen.
Two arguments are returned. wPtr is
a handle or window
pointer to the window - almost like a variable
name that refers to the window or a figure handle. We will use it
later to poke things into the window.
rect describes the
size of the window. You can see how big your monitor's window is by
just typing:
rect
You'll learn more about rect a little later.
when using OpenWindow with Screen,
you can use up to 9 arguments (many of which you will never use).
They are listed in the first line of the help file when you
type:
Screen OpenWindow?
[windowPtr,rect]=Screen('OpenWindow',windowPtrOrScreenNumber
[,color]
[,rect][,pixelSize][,numberOfBuffers][,stereomode][,multisample][,imaging
mode]);
The square brackets [] mean that a
command is optional - if you don't specify it then Screen will use
a default value.
Arguments for Screen
Argument 1. A command
telling Screen what to do –
in this case you want Screen to open a window.
Argument 2. Which monitor you want the
window opened in. In this case you want the Screen opened in
monitor 0 – the one with the menu bar.
Argument 3. The color you want to fill the
window with. So if you wanted to fill the window with red you would
change: [wPtr,rect]=Screen('OpenWindow',screen,
0); to[wPtr,rect]=Screen('OpenWindow',screen, [255 0
0]);
In the first case we are using a single number that is an index
into the colormap. Why do we use the 0-255 range
even though we are using an index into a colormap? Because Screen
is a mex file and was written in C which is a zero-based
language.
In the second case we are using 3 values - for the red, green and
blue guns. If you look at the Display in the control panels you
will notice that your monitor probably thinks that it is a 32 bit
monitor (this is also called having a screen depth of 32bits), but
these values are on an 8 bit scale. This is because allowing the
red gun to take any number between 0-255 takes up 8 bits, allowing
the green gun to take any number between 0-255 takes up 8 bits,
allowing the blue gun to take any number between 0-255 takes up 8
bits. 3x8 is 24. The other 8 bits are padding – don’t ask me what
they are used for.
Argument 4. This tells Screen how big you
want the window to be. The default is to make the window the size
of the entire screen. The order in which you describe the rectangle
in which you are placing the screen can be remembered as LeTteRBox
(Left, Top, Right, Bottom). If your monitor resolution is 1024 by
1280 then you would want the rectangle to start: 0 pixels from the
Left 0 pixels from the Top And go to 1280 pixels towards the Right
1024 pixels towards the Bottom. [wPtr,rect]=Screen('OpenWindow',screen, [], [0 0
1280 1024]);
Why is the first pixel described as 0 instead of 1? Again, because
Screen is a mex file and was written in C which is a zero-based
language. If you wanted a smaller window that was
250 wide and x 100 pixels tall then you would use the
following: [wPtr,rect]=Screen('OpenWindow',screen, [], [0 0
250 100]);
Arguments 5-9. [,pixelSize][,numberOfBuffers][,stereomode][,multisample][,imagingmode])
; are arguments we aren't going to
worry about for now. They will default to the values that we
want.
HideCursor
HideCursor
gets rid of the cursor. It will be restored when you close the
screen unless you have a crash in the middle. If so, you may need
to type ShowCursor in the
command window if your cursor remains missing
Pausing
tic
while toc<2
end
this simply pauses the program for 2 seconds
BlackIndex & WhiteIndex
black=BlackIndex(wPtr);
white=WhiteIndex(wPtr);
These commands find the color lookup table values (clut) given the
screen depth (whether your monitor is using 8bit or 32bit
organization) of your computer that will that will give you black
or white. Weirdly, the values of white and black depend on the
screen depth, especially on Macs.
FillRect
Screen('FillRect',wPtr,black); Screen('FillRect',wPtr,white);
FillRect fills a
rectangle the size of the screen to be black or white
Screen('FillRect', windowPtr [,color] [,rect]
)
You can also specify rgb values for the
color Screen('FillRect', wPtr , [255 0 0
]);
or draw a rectangle that is smaller than the
window Screen('FillRect', wPtr [0 255 0 ] [0 0 50
50])
Flip
Screen(wPtr, 'Flip');
Whenever you draw something it is drawn offscreen in some nebulous
neverland. You then need to Flip the screen so
the offscreen window you drew on comes to the onscreen window – the
one that is actually on the monitor.
Monitors have a refresh rate of something between 60Hz-120Hz (for a
standard monitor). Every refresh begins at the top of the screen,
and moves quickly down the screen in a matter of a few
milliseconds. The flip command simply tells Matlab to refresh the
screen with the image you have drawn offscreen.
Close
Screen('Close', wPtr);
This closes the screen and restores your normal working
environment, including your cursor
If your screen freezes
The Screen window will hide the main menu bar and obscure the
Matlab command window. That can be a problem if your program stops
(perhaps due to an error) before closing the window. The keyboard
will seem to be dead because the output of the keyboard is directed
to the front most window, which belongs to Screen not Matlab, so
Matlab won’t be aware of your typing.
Remain calm.
Force Quit in Windows
ctrl-c
This halts any program. (Type a "c" while holding down the "Ctrl"
key).
Alt-Tab brings the Matlab Command window forward. The screen might
still be hard to make out (or invisible), if you’ve been playing
with the lookup table. Don't let that worry you. Just type
clear Screen
This will cause Matlab to flush Screen. Screen.mex, as part of its
exit procedure, cleans up everything it did, closing all its
windows and restoring the lookup table of all its displays.
You might want to type:
clear all
clear mex
after killing a program, just to make sure everything is back to
normal. clear
mex kills any mex files that might be
still running
If that didn't work?
Sometimes, Ctrl-C fails to halt progams executing in a Matlab
process run with the "-nojvm" option. To halt a runaway
Psychtoolbox script in Psychtoolbox you might resort to the Windows
Task Manager to kill the Screen program. (Use Ctrl-Alt-Delete to
open the Task Manager.)
Force Quit in Mac
Ctrl-c
This halts any program. (Type a "c" while holding down the "Ctrl"
key).
Cmd-0 (command-zero; command is the thing that looks like a four
leaf clover) brings the Matlab Command window forward. The screen
might still be hard to make out (or invisible), if you’ve been
playing with the lookup table. Don't let that worry you. Just
type
clear Screen
This will cause Matlab to flush Screen. Screen.mex, as part of its
exit procedure, cleans up everything it did, closing all its
windows and restoring the lookup table of all its displays.
You might want to type:
clear all
clear mex
after killing a program, just to make sure everything is back to
normal. clear
mex kills any mex files that might be
still running
If that didn't work?
Sometimes, Ctrl-C fails to halt progams executing in a Matlab
process. To halt a runaway Psychtoolbox script in you might resort
to Apple-Command-Escape which
executes "Force Quit" on Matlab, closing Matlab and all of its
windows.
Force Quit in Linux
Ctrl-Alt-Escape , followed by a mouse click
kills the onscreen windows and your Matlab session.
You might want to type:
clear all
clear mex
after killing a program, just to make sure everything is back to
normal. clear
mex kills any mex files that might be
still running
FunkyScreen
Here is another more elaborate example of how you can use
Screen
%
% opens a window using
psychtoolbox,
% makes the window do some funky
things
%
% written for Psychtoolbox 3 on
the PC by IF 3/2007
screenNum=0;
flipSpd=13; % a flip every 13
frames
Screen('Preference', 'Verbosity', 0);
Screen('Preference', 'SkipSyncTests',1);
Screen('Preference', 'VisualDebugLevel',0);
[wPtr,rect]=Screen('OpenWindow',screenNum);
monitorFlipInterval=Screen('GetFlipInterval',
wPtr);
black=BlackIndex(wPtr);
white=WhiteIndex(wPtr);
% blank the Screen and wait a second
Screen('FillRect',wPtr,black);
Screen(wPtr, 'Flip');
HideCursor;
tic
while toc<1
end
% make a rectangle in the middle of the screen flip colors and
size
Screen('FillRect',wPtr,black);
vbl=Screen(wPtr, 'Flip'); % collect the time for the first flip
with vbl
for i=1:10
Screen('FillRect',wPtr,[0
0 255], [100 150 200 250]);
vbl=Screen(wPtr,
'Flip', vbl+(flipSpd*monitorFlipInterval));
%
flip 13 frames after vbl
Screen('FillRect',wPtr,[255
0 0], [100 150 400 450]);
vbl=Screen(wPtr,
'Flip', vbl+(flipSpd*monitorFlipInterval));
end
% blank the screen and wait a while
Screen('FillRect',wPtr,black);
Screen(wPtr, 'Flip',
vbl+(flipSpd*monitorFlipInterval));
tic
while toc<1
end
% make circles flip colors & size
Screen('FillRect',wPtr,black);
vbl=Screen(wPtr, 'Flip');
for i=1:10
Screen('FillOval',wPtr,[0
180 255], [ 500 500 600 600]);
vbl=Screen(wPtr,
'Flip', vbl+(flipSpd*monitorFlipInterval));
Screen('FillOval',wPtr,[0
255 0], [ 400 400 900 700]);
vbl=Screen(wPtr,
'Flip', vbl+(flipSpd*monitorFlipInterval));
end
% blank the Screen and wait a second
Screen('FillRect',wPtr,black);
Screen(wPtr, 'Flip',
vbl+(flipSpd*monitorFlipInterval));
tic
while toc<1
end
% make lines that flip colors
size &
position
Screen('FillRect',wPtr,black);
vbl=Screen(wPtr, 'Flip');
for i=1:10
Screen('DrawLine',wPtr,[0
255 255], 500, 200, 700 ,600, 5);
vbl=Screen(wPtr,
'Flip', vbl+(flipSpd*monitorFlipInterval));
Screen('DrawLine',wPtr,[255
255 0], 100, 600, 600 ,100, 5);
vbl=Screen(wPtr,
'Flip', vbl+(flipSpd*monitorFlipInterval));
end
% blank the Screen and wait a second
Screen('FillRect',wPtr,black);
Screen(wPtr, 'Flip',
vbl+(flipSpd*monitorFlipInterval));
tic
while toc<1
end
% combine the stimuli
Screen('FillRect',wPtr,black);
vbl=Screen(wPtr, 'Flip');
for i=1:10
Screen('FillRect',wPtr,[0
0 255], [100 150 200 250]);
Screen('DrawLine',wPtr,[0
255 255], 500, 200, 700 ,600, 5);
Screen('FillOval',wPtr,[0
180 255], [ 500 500 600 600]);
Screen('TextSize',
wPtr , 150);
Screen('DrawText',
wPtr, 'FUNKY!!', 200, 20, [255 50 255]);
vbl=Screen(wPtr,
'Flip', vbl+(flipSpd*monitorFlipInterval));
Screen('FillRect',wPtr,[255
0 0], [100 150 400 450]);
Screen('FillOval',wPtr,[0
255 0], [ 400 400 900 700]);
Screen('DrawLine',wPtr,[255
255 0], 100, 600, 600 ,100, 5);
vbl=Screen(wPtr,
'Flip', vbl+(flipSpd*monitorFlipInterval));
end
% blank the screen and wait a second
Screen('FillRect',wPtr,black);
Screen(wPtr, 'Flip',
vbl+(flipSpd*monitorFlipInterval));
tic
while toc<1
end
Screen('CloseAll');
ShowCursor
Code comments on FunkyScreen
flipSpd=13;
Here you define flipSpd, you are going to make the display flip
every 13 frames.
monitorFlipInterval=Screen('GetFlipInterval',
wPtr)
You can find out how fast your monitor flips using
'GetFlipInterval'. 1/monitorFlipInterval will tell you the frame
rate in Hz of your monitor.
Screen('Preference', 'Verbosity', 0);
Screen('Preference', 'SkipSyncTests',1);
Screen('Preference', 'VisualDebugLevel',0);
These tell Matlab not to spit out an annoying series of factoids
when you call Screen.
vbl=Screen(wPtr, 'Flip');
This time when you flipped the window you made Screen return the
time (according to the computer clock) that it did the flip. That
time is saved as vbl.
Screen('FillRect',wPtr,[0 0 255], [100 150 200
250]);
Here we are using FillRect again, but this time we are defining the
rect as only being a subset of the entire screen and we are using a
color. Remember that the rect is defined as LeTteRBox.
vbl=Screen(wPtr, 'Flip',
vbl+(flipSpd*monitorFlipInterval));
We flip the screen, but this time we are telling it to flip at time
| vbl + (13 * monitorFlipInterval)|
This means it will flip 13 frames after the flip where we saved the
time of the flip in the variable vbl.
We keep doing the same thing again, but each time vbl refers to the
flip that happened on the previous flip. So between each flip there
is a 13 frame delay.
Screen('FillOval',wPtr,[0 180 255], [ 500 500
600 600]);
FillOval works just like FillRect except that it draws ovals
instead of squares.
Screen('DrawLine',wPtr,[0 255 255], 500, 200,
700 ,600, 5);
DrawLine doesn’t
take a rect as an argument. Instead it takes in four separate
arguments
starting horizontal position
starting vertical position
ending horizontal position
ending vertical position I guess the mnemonic for that could be
HumVee?
Screen('TextSize', wPtr , 150);
Screen('DrawText', wPtr, 'FUNKY!!', 200, 20,
[255 50 255]);
Here we are drawing text on the screen. First we define the size of
the text as having a font size of 150. Then we draw it on the
screen. 200 and 20 refer
to the starting horizontal and vertical positions of where you want
the text placed (HumVee again).
[255 50 255] refers
to the color of the text.
Screen('FillRect',wPtr,[0 0 255], [100 150 200
250]);
Screen('DrawLine',wPtr,[0 255 255], 500, 200,
700 ,600, 5);
Screen('FillOval',wPtr,[0 180 255], [ 500 500
600 600]);
Screen('TextSize', wPtr , 150);
Screen('DrawText', wPtr, 'FUNKY!!', 200, 20,
[255 50 255]);
vbl=Screen(wPtr, 'Flip',
vbl+(flipSpd*monitorFlipInterval));
Here we are drawing more than one thing on the offscreen window
before we flip it to the front. The order you draw things in
matters, since things will be drawn on top of each other.
Putting up Matrix Images
% opens a window using Psychtoolbox,
% puts up a 2D image and then a 3D image
%
% written for Psychtoolbox 3 on the PC by IF
3/2007
screen=0;
Screen('Preference', 'Verbosity', 0);
Screen('Preference', 'SkipSyncTests',1);
Screen('Preference', 'VisualDebugLevel',0);
[wPtr,rect]=Screen('OpenWindow',screen);
HideCursor;
black=BlackIndex(wPtr);
Screen('FillRect',wPtr,black);
Screen(wPtr, 'Flip');
tic
while toc<1
end
image2D=255*rand(100, 100);
textureIndex=Screen('MakeTexture', wPtr,
image2D);
Screen('DrawTexture', wPtr, textureIndex);
Screen(wPtr, 'Flip');
tic
while toc<2
end
image3D=255*rand(100, 100, 3);
textureIndex=Screen('MakeTexture', wPtr,
image3D);
Screen('DrawTexture', wPtr, textureIndex, [], rect, [],0
);
Screen(wPtr, 'Flip');
tic
while toc<2
end
Screen('Close', wPtr);
Note that putting up a matrix is slightly
different from drawing a rectangle or an oval. You can't directly
put the matrix onto the
window.
There is instead an extra step where you need to create
a textureIndex using
the Screen command 'MakeTexture'.
This textureIndex is an index (this might be a moment to re-read
the section on 'references', 'indices', 'handles' and 'pointers')
into an OpenGL structure that contains the matrix transformed into
an image. Once you have created the texture, you can then draw it
on the screen.
Make sure you remember this - it's one of the mistakes that
beginners with Psychtoolbox often make.
FunkyJon.m
Here's a version of funkyscreen done by a student in a previous
class with way too much spare time on his hands.
% This is my Funky li'l m_file
written to demonstrate psychtoolbox
%
% Written by Jon D. Howe
4/16/2007
clear all
% Initialize variables
screenNum=0;
flipSpd=25; % flip every 25 frames
[wPtr,rect]=Screen('OpenWindow',screenNum, 0,
[]);
monitorFlipInterval=Screen('GetFlipInterval',wPtr);
black=BlackIndex(wPtr);
white=WhiteIndex(wPtr);
HideCursor;
% blank screen and wait a second
Screen('FillRect',wPtr,black);
Screen('Flip',wPtr);
tic
while toc<.2>
end
% Flip and collect th e time of the flip in vbl
vbl=Screen('Flip', wPtr);
% Draw Background
Screen('FillRect', wPtr, [100 255 255]);
Screen('FillRect', wPtr, [0 255 0], [0 2*rect(4)/3 rect(3)
rect(4)])
% Draw house
Screen('FillRect', wPtr, [0 0 255], [420 300 680
600]);
Screen('FillPoly', wPtr, [100 0 0], [420 300; 540 200; 680
300]);
% Draw roof
Screen('DrawLine', wPtr, [50 50 50], 410, 310, 540, 200,
5);
Screen('DrawLine', wPtr, [50 50 50], 690, 310, 540, 200,
5);
% Draw doors and windows
% door
Screen('FillRect', wPtr, [200 200 0], [520 450 600
600]);
% window
Screen('FillRect', wPtr, [175 200 256], [440 380 500
440]);
Screen('FrameRect', wPtr, [0 0 0], [440 380 500 440],
3);
Screen('DrawLine', wPtr, [0 0 0], 470, 380, 470, 440,
3);
Screen('DrawLine', wPtr, [0 0 0], 440, 410, 500, 410,
3);
% gable window
Screen('FillArc', wPtr, [175 200 256], [520, 260, 600,
320],270,180);
Screen('FrameArc', wPtr, [0 0 0], [520 260 600
320],270,180,3);
% Draw tree
Screen('FillRect', wPtr, [100 100 0], [200 400 230
700]);
Screen('FillOval', wPtr, [0 150 0], [50 250 370
550]);
% Draw sun
Screen('FillOval', wPtr, [256 256 0], [760 20 920
180]);
Screen('DrawLine', wPtr, [0 0 0], 850, 75, 870, 75,
2);
Screen('FrameOval', wPtr, [0 0 0], [800 65 820 85],
2);
Screen('FrameArc', wPtr, [0 0 0], [800 85 870 160], 90, 180,
2);
% Draw name
Screen('TextSize', wPtr, 72);
Screen('DrawText', wPtr, 'Funky Jon''s House', 200, 100, [256 256
256]);
vbl=Screen('Flip', wPtr, vbl+(flipSpd*monitorFlipInterval),
2);
tic;
while toc<3
end
Screen('CloseAll');
ShowCursor;