/usr/share/psychtoolbox-3/PsychDemos/PsychExampleExperiments/MullerLyerIllusion.m is in psychtoolbox-3-common 3.0.11.20131230.dfsg1-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 | function results = MullerLyerIllusion(subID)
% results = MullerLyerIllusion(subID)
%
% Presenting the Muller-Lyer Illusion with the Psychtoolbox, complete experiment.
%
% Input:
%
% subID = subject Id (scalar), defaults to 66
%
% Output:
%
% 'results' is a numerical matrix with one row per trial and columns:
% colHeaders = {'subID', 'trial no', 'trial ID', 'length l1', 'headdir l1',...
% 'length l2', 'headdir l2', 'length ratio', 'correct', 'rt PTB', 'rt ML'}
%
% In this experiment two lines (l1 and l2) are presented, where each line can have
% inward or outward pointing arrow heads at its ends.
% subjects are asked to judge the relative length of the basic lines
% and to respond by pressing 's' for same or 'd' for different
%
% correctness and reaction times are recorded, the latter by two
% different methods in order to compare precision:
% rt PTB relies on PTB commands which are supposedly more precise
% rt ML uses the Matlab's native tic/toc stopwatch
%
% This experiment is a counterbalanced 2x2x2x2 design with
% the factors line length (l1, l2) and head direction (l1, l2)
% The 16 test trials are presented in randomized order, following 3
% randomly drawn training trials
% The exact design is defined in condtable (see below), where each line
% stands for one trial and the columns for the four factors
%
% line length can be either 1 or 2, these values will be taken as
% indices into the 1 x 2 vector hll (half line length, difference of 10%)
% using indices allows the stimuli to be scaled by a random factor in each trial
%
% head direction can be -1 (outward pointing), 0 (no head) or 1
% (inward pointing); 0 is not used in the present design
%
%
% Written by N. Ruh, 15/02/2008.
%
% Exemplary reference:
%
% Restle F & Decker J (1977) Size of the Mueller-Lyer illusion as a
% function of its dimensions: Theory and data. Perception & Psychophysics 21:489�503
%
% History:
% 3/3/2008 Included in Psychtoolbox (MK).
% Make sure the script is running on Psychtoolbox-3:
AssertOpenGL;
%set default values for input arguments
if ~exist('subID','var')
subID=66;
end
%warn if duplicate sub ID
fileName=['MLIexpSubj' num2str(subID) '.txt'];
if exist(fileName,'file')
if ~IsOctave
resp=questdlg({['the file ' fileName 'already exists']; 'do you want to overwrite it?'},...
'duplicate warning','cancel','ok','ok');
else
resp=input(['the file ' fileName ' already exists. do you want to overwrite it? [Type ok for overwrite]'], 's');
end
if ~strcmp(resp,'ok') %abort experiment if overwriting was not confirmed
disp('experiment aborted')
return
end
end
%prepare conditions;
%the first two elements in each row code for linelength,
%the last two for head orientation
condtable=[ 1 1 1 1;
1 2 1 1;
2 1 1 1;
2 2 1 1;
1 1 -1 1;
1 2 -1 1;
2 1 -1 1;
2 2 -1 1;
1 1 1 -1;
1 2 1 -1;
2 1 1 -1;
2 2 1 -1;
1 1 -1 -1;
1 2 -1 -1;
2 1 -1 -1;
2 2 -1 -1];
ntrials=size(condtable,1);
%re-order the 16 trials randomly
shuffeldTrialIDs=randperm(ntrials);
%number of training trials
ntrain=3;
%attach a randomly drawn subsample as training trials
order=[ceil(rand(1,ntrain)*ntrials), shuffeldTrialIDs];
%Prepare output
colHeaders = {'subID', 'trial no', 'trial ID', 'length l1', 'headdir l1',...
'length l2', 'headdir l2', 'length ratio', 'correct', 'rt PTB', 'rt ML'};
results=NaN * ones(length(order),length(colHeaders)); %preallocate results matrix
%head=[-1 0 1]; %we are currently using only +/- 1, see condtable
lw=3; %line width of stimuli
%when working with the PTB it is a good idea to enclose the whole body of your program
%in a try ... catch ... end construct. This will often prevent you from getting stuck
%in the PTB full screen mode
try
% Enable unified mode of KbName, so KbName accepts identical key names on
% all operating systems (not absolutely necessary, but good practice):
KbName('UnifyKeyNames');
%funnily enough, the very first call to KbCheck takes itself some
%time - after this it is in the cache and very fast
%to make absolutely sure, we thus call it here once for no other
%reason than to get it cached. This btw. is true for all major
%functions in Matlab, so calling each of them once before entering the
%trial loop will make sure that the 1st trial goes smooth wrt. timing.
KbCheck;
%disable output of keypresses to Matlab. !!!use with care!!!!!!
%if the program gets stuck you might end up with a dead keyboard
%if this happens, press CTRL-C to reenable keyboard handling -- it is
%the only key still recognized.
ListenChar(2);
%Set higher DebugLevel, so that you don't get all kinds of messages flashed
%at you each time you start the experiment:
olddebuglevel=Screen('Preference', 'VisualDebuglevel', 3);
%Choosing the display with the highest display number is
%a best guess about where you want the stimulus displayed.
%usually there will be only one screen with id = 0, unless you use a
%multi-display setup:
screens=Screen('Screens');
screenNumber=max(screens);
%open an (the only) onscreen Window, if you give only two input arguments
%this will make the full screen white (=default)
[expWin,rect]=Screen('OpenWindow',screenNumber);
%alternative: replace the above with smaller window for testing
% [expWin,rect]=Screen('OpenWindow',screenNumber,[],[10 20 1200 700]);
%NOTE that smaller windows can induce synchronisation problems
%and other issues, so they're not suitable for running real experiment
%sessions. See >> help SyncTrouble
%get the midpoint (mx, my) of this window, x and y
[mx, my] = RectCenter(rect);
%get rid of the mouse cursor, we don't have anything to click at anyway
HideCursor;
% %Syntax for querying user input, e.g. subject initials:
% reply=Ask(expWin,'Enter subject initials: ',[],[],'GetChar',RectLeft,RectTop,20);
%Preparing and displaying the welcome screen
% We choose a text size of 24 pixels - Well readable on most screens:
Screen('TextSize', expWin, 24);
% This is our intro text. The '\n' sequence creates a line-feed:
myText = ['In this experiment you are asked to judge\n' ...
'the relative length of two horizontal lines\n' ...
' Press s if the lines have the same length \n' ...
' Press d if the lines have different length\n' ...
'You will begin with ' num2str(ntrain) ' training trials\n' ...
' (Press any key to start training)\n' ];
% Draw 'myText', centered in the display window:
DrawFormattedText(expWin, myText, 'center', 'center');
% This chunk of code would do roughly the same: It uses the lower-level
% 'DrawText' subcommand to draw text. DrawFormattedText is a
% convenience wrapper that provides basic text formatting functions.
% See 'help DrawFormattedTextDemo' for a demo of its capabilities...
%
% lm=150; %left margin, adjust to suit the size of your screen
% Screen('DrawText', expWin, 'In this experiment you are asked to judge', lm, 50);
% Screen('DrawText', expWin, 'the relative length of two horizontal lines', lm, 80);
% Screen('DrawText', expWin, ' press s if the lines have the same length', lm, 110);
% Screen('DrawText', expWin, ' press d if the lines have different lengths', lm, 140);
% Screen('DrawText', expWin, ['you will begin with ' num2str(ntrain) ' training trials'], lm, 170);
% Screen('DrawText', expWin, ' (press any key to start training)', lm, 250);
% Show the drawn text at next display refresh cycle:
Screen('Flip', expWin);
% Wait for key stroke. This will first make sure all keys are
% released, then wait for a keypress and release:
KbWait([], 3);
% %an example of preparing an offScreenwindow (for repeated use and fast drawing)
% [fixcross,rect2]=Screen('OpenOffscreenWindow',screenNumber,[],[0 0 20 20]);
% Screen('drawline',fixcross,[0 0 0],10,0,10,20,2);%mx-10,my,mx+10,my
% Screen('drawline',fixcross,[0 0 0],0,10,20,10,2);%mx,my-10,mx,my+10
% Another way to create a fixation cross: Doing the above with textures,
% by preparing a little Matlab matrix with the image of a fixation
% cross: --> Choose whatever you like more.
FixCr=ones(20,20)*255;
FixCr(10:11,:)=0;
FixCr(:,10:11)=0; %try imagesc(FixCr) to display the result in Matlab
fixcross = Screen('MakeTexture',expWin,FixCr);
%start trials loop (over training and test trials)
for i=1:length(order)
%prepare and display end of training/start experiment screen
if i==ntrain+1 %before the first test trial
DrawFormattedText(expWin, 'Are you ready for the experiment?\n(Press any key to start experiment)', 'center', 'center');
Screen('Flip', expWin);
KbWait([], 3);
end
% Copy the content of the previously prepared texture or offscreenWindow
% into the backbuffer of the onscreen window, then flip it to the front
% NOTE that offscreen windows and textures are almost the same
% thing. Btw. although we specify the target region, this is not
% strictly neccessary. A Screen('DrawTexture', expWin, fixcross);
% would yield exactly the same result, as all textures are centered
% in the target window by default.
Screen('DrawTexture', expWin, fixcross,[],[mx-10,my-10,mx+10,my+10]);
% We show the fixation cross at next display refresh cycle and
% store the onset time of the fixation cross in 'tfixation'. Later
% on we will use that as baseline to make sure the actual Mueller
% Lyer test stim is shown 0.5 secs after onset of fixation:
tfixation = Screen('Flip', expWin);
%Prepare stimulus characteristics, make all aspects of the stimuli
%proportional to stimsize so it can be dynamically changed
stimsize=rand*100+50; %between 50 and 150 pixels
hll=[stimsize, stimsize*0.9]; %halflinelength, difference of 10%
hos=stimsize*.8; %headoffset
voff=stimsize*1.5; %vertical distance between lines
%look up the index in the correct line of current trial and find the
%corresponding item in hll (half line length)
%the identity of the current line is governed by the scrambled indices in order
l_hll = hll(condtable(order(i),(1)));
%look up the direction of the header in the current line of condtable
l_head = condtable(order(i),(3));
%find horizontal offset according to this line's hearer direction
l_hos=hos*l_head;
%same again for the second stimulus/line
u_hll = hll(condtable(order(i),(2)));
u_head = condtable(order(i),(4));
u_hos=hos*u_head;
%draw stimuli into backbuffer
Screen('DrawLine', expWin , 0, mx-l_hll, my-voff, mx+l_hll, my-voff, lw);
if l_hos~=0
Screen('DrawLine', expWin , 0, mx-l_hll, my-voff, mx-l_hll+l_hos, my-voff+hos/2, lw);
Screen('DrawLine', expWin , 0, mx-l_hll, my-voff, mx-l_hll+l_hos, my-voff-hos/2, lw);
Screen('DrawLine', expWin , 0, mx+l_hll, my-voff, mx+l_hll-l_hos, my-voff+hos/2, lw);
Screen('DrawLine', expWin , 0, mx+l_hll, my-voff, mx+l_hll-l_hos, my-voff-hos/2, lw);
end
Screen('DrawLine', expWin , 0, mx-u_hll, my+voff, mx+u_hll, my+voff, lw);
if u_hos~=0
Screen('DrawLine', expWin , 0, mx-u_hll, my+voff, mx-u_hll+u_hos, my+voff+hos/2, lw);
Screen('DrawLine', expWin , 0, mx-u_hll, my+voff, mx-u_hll+u_hos, my+voff-hos/2, lw);
Screen('DrawLine', expWin , 0, mx+u_hll, my+voff, mx+u_hll-u_hos, my+voff+hos/2, lw);
Screen('DrawLine', expWin , 0, mx+u_hll, my+voff, mx+u_hll-u_hos, my+voff-hos/2, lw);
end
%this would tell PTB that no further drawing commands will occur
%before the next screen 'flip'. Apparently this can improve performance
%telapsed is the time since the last flip command; use this if
%you want to test how long it takes to draw into the backbuffer
% telapsed = Screen('DrawingFinished', expWin, [], 1);
%However, its not needed here...
%display stimuli and get onset time (two alternative ways). We ask
%to show the stim 0.5 seconds after onset 'tfixation' of the
%fixation cross:
[VBLTimestamp, StimulusOnsetTime, FlipTimestamp]=Screen('Flip', expWin, tfixation + 0.5);
tic;
%these different timestamps are not exactly the same, e.g.:
% plot([VBLTimestamp StimulusOnsetTime FlipTimestamp tic])
%the difference is negligible for most experiments
%record response time, two methods again
%this is just to compare between Matlab and PTB timing.
%In your experiment, you should settle for one method -->
%the Psychtoolbox method of using 'StimulusOnsetTime' seems to be
%the more reliable solution, specifically on varying hardware
%setups or under suboptimal conditions
[resptime, keyCode] = KbWait;
MLrt=toc;
rt=resptime-StimulusOnsetTime;
%find out which key was pressed
cc=KbName(keyCode); %translate code into letter (string)
%calculate performance or detect forced exit
if isempty(cc) || strcmp(cc,'ESCAPE')
break; %break out of trials loop, but perform all the cleanup things
%and give back results collected so far
elseif ~any(strcmp(cc,'s') || strcmp(cc,'d'))
anscorrect = 66;
elseif u_hll==l_hll && strcmp(cc,'s')
anscorrect = 1;
elseif u_hll~=l_hll && strcmp(cc,'d')
anscorrect = 1;
else
anscorrect = 0;
end
%enter results in matrix
results(i,:) = [subID, i-ntrain, order(i), l_hll*2, l_head, u_hll*2, u_head, u_hll/l_hll, anscorrect, rt, MLrt];
%beep if the response was incorrect
if anscorrect ~=1
beep;
end
%show between trial prompt and wait for button press
DrawFormattedText(expWin, 'Press any key to start next trial', 'center', 'center');
Screen('Flip', expWin);
KbWait([], 3); %wait for keystroke
end %of trials loop
%write results to comma delimited text file (use '\t' for tabs)
dlmwrite(fileName, results, 'delimiter', ',', 'precision', 6);
% %alternative: write to excel format
% xlswrite(['MLIexpSubj' num2str(subID) '.xls'],[colHeaders; num2cell(results)]);
%calculate and display performance feedback
performance_errors=mean(results(results(:,9)~=66,9));
DrawFormattedText(expWin, ['You were correct in ' num2str(performance_errors*100,2) '% of trials.\nThank you for participating!'], 'center', 'center');
Screen('Flip', expWin);
KbWait([], 2); %wait for keystroke
%clean up before exit
ShowCursor;
sca; %or Screen('CloseAll');
ListenChar(0);
%return to olddebuglevel
Screen('Preference', 'VisualDebuglevel', olddebuglevel);
catch
% This section is executed only in case an error happens in the
% experiment code implemented between try and catch...
ShowCursor;
Screen('CloseAll'); %or sca
ListenChar(0);
Screen('Preference', 'VisualDebuglevel', olddebuglevel);
%output the error message
psychrethrow(psychlasterror);
end
|