Hi there, grateful for any assistance or pointers here.
I am running Ubuntu 20.04 LTS, Psychtoolbox 3.0.18.12 and Mesa Intel UHD Graphics CML GT2 on Matlab 2022b.
The task is fairly simple - a series of pictures are presented and the participant rates the valence of each. In the first screen you press the space bar to begin.
The task works on a colleague’s machine running Windows 10 and Intel graphics P630 but on my machine the keyboard is unresponsive - although the task can be exited by pressing “i” for some reason. I have run another Psychtoolbox task on this machine with no issues so I am confused as to why I have this problem. Is there some issue with Screen of Keybinding here?
Code below:
function ocd_task_rate_images_mri_phil(pcateg,pnpics)
% Enable unified mode of KbName, so KbName accepts identical key names on all operating systems:
KbName('UnifyKeyNames');
ex.ESCAPE = KbName('escape'); % key to exit experiment
%
% FUNCTION ocd_task_rate_images_03(mode,pcateg,pnpics)
%
% Runs the image rating task for the OCD trial.
% MODE: 'mri' or 'ephys' - controls stimulus timing.
% PCATEG: Specific picture category for this patient .
% PNPICS: Factor for how many images to use from this category (default is 2 for
% twcie as many).
% Output is written to a .mat file (in the current folder) using the name of
% the function (eg ocd_task_rate_images) and the current date and time.
% TO DO
% done: keypresses '1' '2' with +/-5 level rating scale
% done: make sure results are saved after ESC
% done: select heaps of images, keep going until ESC
% done: optional blank fixation delay period between images
% done: add params as required
% choose 1 or more folders to pick extra images from
%
% FOR CLINICAL VERSION ENSURE:
% - clinical_ready = true; % Set to true when ready for clinical use
% - do_sync_test = false; % Sync tests fail on MRI setup
% - for ephys screennum = 0; mri = 2;
% - rethrow(ALLERRS); % must be activated
% - pause_every_ntrials = 40
% - picdir is set correctly
% All these should be set to true for clinical use
clinical_ready = true; % Set to true when ready for clinical use
do_sync_test = true; % Sync tests fail on MRI setup
% Params
nratesteps = 5; % Num rating steps in each direction (up and down)
nloadimages = 200; % How many images to load in total
totratesteps = nratesteps*2+1;
mode1 = 'm';
blanktime = 2; % Blank period in sec between images
image_only_time = 2; % Display image without rating bar for n secs
nulltime = 12; % Blank screen for 12 secs after every 5th image
keytimeout = 2; % 2 sec timeout after last keypress
bartimeout = 5; % 5 sec timeout after rating bar appears
pause_after_sync = 5; % 5 secs pause after syncing
pause_every_ntrials = 40; % Pause and re-sync after every n images
screennum = 0; %1;
forecolr = [128 128 128];
% Image folder
picdir = 'IAPS-1-20-Images';
% Check other arguments
if nargin < 1; pcateg = ''; end
if nargin < 2; pnpics = 2; end
% New random seed
rand('twister',sum(100*clock()))
try
% Not for when running real experiments
if ~do_sync_test
Screen('Preference','SkipSyncTests',1);
else
Screen('Preference','SkipSyncTests',0);
end
% Load category folders
dirlist = dir(fullfile(picdir));
% Remove any starting with . and also remove the patient specific folder
di = 1;
while di <= length(dirlist)
if dirlist(di).name(1) == '.' || ~dirlist(di).isdir || strcmpi(dirlist(di).name,pcateg)
dirlist(di) = [];
else
di = di + 1;
end
end
% Load all the image names from each folder
disp('Please wait... loading images');
images = {};
piclist = {};
picfolder = {};
for di = 1:length(dirlist)
% Load the image names and then remove any starting with '.'
fillist = dir(fullfile(picdir,dirlist(di).name,'*.jpg'));
fi = 1;
while fi <= length(fillist)
if fillist(fi).name(1) == '.'; fillist(fi) = [];
else fi = fi + 1;
end
end
for ii = 1:length(fillist)
piclist{end+1} = fillist(ii).name;
picfolder{end+1} = dirlist(di).name;
end
end
totpic_norm = length(piclist); % Num normal pics
% Load extra image names from the patient specific folder
if ~isempty(pcateg)
fillist = dir(fullfile(picdir,pcateg,'*.jpg'));
if isempty(fillist)
error(['Folder ' pcateg ' does not exist']);
end
fi = 1;
while fi <= length(fillist)
if fillist(fi).name(1) == '.'; fillist(fi) = [];
else fi = fi + 1;
end
end
for ii = 1:length(fillist)
piclist{end+1} = fillist(ii).name;
picfolder{end+1} = pcateg;
end
end
totpic_subj = length(piclist)-totpic_norm; % Num subject-specific pics
% Now choose images 'randomly'
if totpic_subj > 0
nsubjpics = ceil(nloadimages/length(dirlist)*pnpics);
else
nsubjpics = 0;
pnpics = 0;
end
if totpic_subj < nsubjpics
error(['Too few images in patient-specific folder ' fullfile(picdir,pcateg)]);
end
% Choose pics in groups of length equal to the number of categories to
% make sure that patient specific images are 'evenly but randomly' spread
picorder = [];
normi = 0;
subji = 0;
rp_norm = randperm(totpic_norm);
rp_subj = randperm(totpic_subj);
while length(images) < nloadimages
rp_loop = randperm(length(dirlist)+ceil(pnpics));
for i = 1:length(rp_loop)
if rp_loop(i) <= length(dirlist)
normi = normi + 1;
picorder(end+1) = rp_norm(normi);
else
subji = subji + 1;
picorder(end+1) = totpic_norm + rp_subj(subji);
end
images{end+1} = imread(fullfile(picdir,picfolder{picorder(end)},piclist{picorder(end)}));
end
end
disp('Done.');
drawnow();
% Open a window
[window,winrect] = Screen(screennum,'OpenWindow');
WaitSecs(1);
wc = winrect(3:4)/2; % window centre
% Set default text properties
Screen('TextSize',window,25);
Screen('TextFont',window,'Helvetica');
if clinical_ready
HideCursor();
end
% Rating bar dimensions - first the outline and then the bar itself
boutrect = [winrect(3)*0.093,winrect(4)*0.14,winrect(3)*0.907,winrect(4)*0.21];
brect = [winrect(3)*0.1,winrect(4)*0.15,winrect(3)*0.9,winrect(4)*0.2];
blen = brect(3)-brect(1);
% Banner until SPACE BAR
Screen('FillRect',window,[0 0 0]);
Screen('DrawText',window,'OCD Image Rating (OCDIR) Task',winrect(3)*0.2,winrect(4)*0.4,forecolr);
if ~clinical_ready
Screen('DrawText',window,'Demonstration only. Not for Clinical use.',winrect(3)*0.2,winrect(4)*0.5,[255 0 0]);
end
Screen('DrawText',window,'Press SPACE to continue',winrect(3)*0.2,winrect(4)*0.7,forecolr/2);
Screen(window,'Flip'); kidx = zeros(1,256); while ~(kidx(27)||kidx(32)); [~,kidx] = KbPressWait(); end % Wait for SPACE
if kidx(27); ShowCursor(); Screen('CloseAll'); return; end % Check for ESC key
% Instructions
Screen('FillRect',window,[0 0 0]);
DrawFormattedText(window,['INSTRUCTIONS:\n\n1. Look at each image.\n\n'...
'2. Rate the image by clicking buttons to control the bar at the top of the screen.\n'],'center','center',forecolr,75,[],[],1.5);
Screen('DrawText',window,'Press SPACE to continue',winrect(3)*0.2,winrect(4)*0.7,forecolr/2);
Screen(window,'Flip'); kidx = zeros(1,256); while ~(kidx(27)||kidx(32)); [~,kidx] = KbPressWait(); end % Wait for SPACE
if kidx(27); ShowCursor(); Screen('CloseAll'); return; end % Check for ESC key
% Clear image rating and response times
test_rating = [];
test_clicktime = [];
test_timing = zeros(0,3);
kidx = zeros(1,256);
% Loop thru images
totnimages = length(images); %length(textures)
imgn = 0;
while imgn < totnimages
% SYNC with MRI
esckey = sync_mri();
if esckey; ShowCursor(); Screen('CloseAll'); break; end % Check for ESC key
% Loop thru this block of images
lastloop = min(imgn+pause_every_ntrials,totnimages);
for imgn = imgn+1:lastloop
disp(sprintf('Image %d/%d',imgn,totnimages));
% Fixation cross if wanted
if blanktime > 0
% Display cross for trial start duration
Screen('FillRect',window,[0 0 0]);
Screen('DrawLine',window,forecolr,wc(1),wc(2)+100,wc(1),wc(2)-100,10);
Screen('DrawLine',window,forecolr,wc(1)-100,wc(2),wc(1)+100,wc(2),10);
Screen(window,'Flip'); WaitSecs(blanktime);
end
% Display image and wait for 2 secs
texture = Screen('MakeTexture',window,images{imgn});
Screen('FillRect',window,[0 0 0]);
Screen('DrawTexture',window,texture); %textures{ceil(rand()*length(textures))});
Screen(window,'Flip',[],1); test_timing(imgn,1) = GetSecs();
WaitSecs(image_only_time);
% Display rating bar - first the outline
Screen('FillRect',window,forecolr/2,boutrect);
for bstp = 1:totratesteps
srect = [brect(1)+(bstp-1)*blen/totratesteps,brect(2),brect(1)+bstp*blen/totratesteps,brect(4)];
if bstp <= nratesteps+1
Screen('FillRect',window,[255 255*(bstp)/(nratesteps+1) 255*(bstp)/(nratesteps+1)],srect);
else
Screen('FillRect',window,[255*(totratesteps-bstp)/nratesteps 255 255*(totratesteps-bstp)/nratesteps],srect);
end
end
% Current rating in the centre
ratepos = nratesteps+1;
% Now move the rating selection box based on the keypress
bardisptim = GetSecs();
lastkeytim = bardisptim;
kidx(32) = 1;
while any(kidx~=0)
% Redraw the current rating in its proper colour
srect = [brect(1)+(ratepos-1)*blen/totratesteps,brect(2),brect(1)+ratepos*blen/totratesteps,brect(4)];
if ratepos <= nratesteps+1
Screen('FillRect',window,[255 255*(ratepos)/(nratesteps+1) 255*(ratepos)/(nratesteps+1)],srect);
else
Screen('FillRect',window,[255*(totratesteps-ratepos)/nratesteps 255 255*(totratesteps-ratepos)/nratesteps],srect);
end
% Process keypress
if kidx(49)
% Move left
ratepos = max(ratepos-1,1);
lastkeytim = GetSecs();
elseif kidx(50)
% Move right
ratepos = min(ratepos+1,totratesteps);
lastkeytim = GetSecs();
end
% Redraw the current rating in the selection colour
srect = [brect(1)+(ratepos-1)*blen/totratesteps,brect(2),brect(1)+ratepos*blen/totratesteps,brect(4)];
Screen('FrameRect',window,[0 0 0],srect,5);
Screen(window,'Flip',[],1);
% Get next keypress with a timeout
[test_timing(imgn,3), kidx] = KbPressWait([],min(lastkeytim+keytimeout,bardisptim+bartimeout));
if kidx(27); imgn = imgn-1; break; end % Check for ESC key
if test_timing(imgn,2) == 0
test_timing(imgn,2) = test_timing(imgn,3);
end
end
if kidx(27); break; end % Check for ESC key
% Calculate response
timing_sync = 0
test_timing(imgn,2:3) = test_timing(imgn,2:3) - keytimeout;
test_timing(imgn,:) = test_timing(imgn,:) - timing_sync;
test_clicktime(imgn) = (test_timing(imgn,2)-test_timing(imgn,1))*1000; % click time in ms
%test_rating(imgn) = max(min((mx-brect(1)-blen/2)/(blen/2),1),-1); % Subject rating in [-1,1]
test_rating(imgn) = (ratepos-1-nratesteps)/nratesteps; % Subject rating in [-1,1]
% Close texture
Screen('Close',texture);
% NULL trial every 5 images
if mod(imgn,5)==0 && imgn~=lastloop
Screen('FillRect',window,[0 0 0]);
% Screen('DrawLine',window,forecolr,wc(1),wc(2)+100,wc(1),wc(2)-100,10);
% Screen('DrawLine',window,forecolr,wc(1)-100,wc(2),wc(1)+100,wc(2),10);
Screen(window,'Flip'); WaitSecs(nulltime);
end
end
% Wait for SPACE BAR
if imgn < totnimages
Screen('FillRect',window,[0 0 0]); Screen(window,'Flip'); % Blank screen
disp('PAUSED for rest. Press SPACE BAR to continue');
kidx = zeros(1,256); while ~(kidx(27)||kidx(32)); [~,kidx] = KbPressWait(); end % Wait for SPACE
esckey = kidx(27); if esckey; break; end % Check for ESC key
disp('Continuing');
end
end
% Save all the data
test_timing = test_timing;
piclist = piclist(picorder); % Re-order image names into presentation order
picfolder = picfolder(picorder);
savnam = [mfilename() '_' datestr(now(),30)];
save(savnam,'totnimages','imgn','piclist','picfolder','picorder','test_clicktime',...
'test_rating','test_timing','nratesteps','keytimeout','clinical_ready','do_sync_test',...
'screennum','picdir','totratesteps','blanktime','mode1','pcateg','pnpics');
disp(['Results saved to ' savnam '.mat']);
% Finished
ShowCursor();
Screen('CloseAll');
% Show reaction times etc
if ~clinical_ready
figure; subplot(2,1,1); plot(test_clicktime), xlabel('Trial #'); ylabel('Reaction time (ms)'); title('Reaction times');
subplot(2,1,2); plot(test_rating); ylim([-1 1]); xlabel('Trial #'); ylabel('Rating (-1 - 1)'); title('Image rating');
figure; plot(test_rating,(test_clicktime),'.'); xlabel('Rating'); ylabel('Click time');
end
catch ALLERRS
Screen('CloseAll');
ShowCursor;
Priority(0);
disp('ERROR catch');
rethrow(ALLERRS);
%keyboard;
%psychrethrow(psychlasterror);
end
%---------------------------------------------------------
% SYNC with MRI
%
function esckey = sync_mri()
% SYNC PULSE TIMING
Screen('FillRect',window,[0 0 0]); Screen(window,'Flip',[],1); % Blank screen
GetSecs(); timing_sync = 0; % make sure tic function and variable are in mem
disp('');
disp('Waiting for MRI sync signal ''5''.');
disp('SEND SYNC PULSE to continue'); drawnow();
esckey = 0;
kidx = zeros(1,256);
while ~kidx(53)
[~,~,kidx] = KbCheck; esckey = kidx(27); if esckey; return; end % Check for ESC key
end
timing_sync = GetSecs(); % Sync received
disp('SYNC received!');
% Pause for a bit
disp(['Pausing for ' num2str(pause_after_sync) ' secs...']); drawnow();
WaitSecs(pause_after_sync);
disp('Pause complete, continuing...');
end
end
Thank you again. Phil