FX2MYQ66-202221011134:f1f8bebaf73ec8b7e071812a60bfd2461604a2b8e900cf85b7430f714ba5d65f
PsychtoolboxVersion Output:
‘3.0.18 – Flavor: Manual Install, 26-Oct-2021 18:56:38.
The desktop computer that I am using has a NVIDIA GeForce GT 710 GPU, an Intel® Core™ i7-8700 CPU @ 3.20 GHz, and 16 GB of memory. Its operating system is Windows 10 Enterprise, Version 20H2, OS build 19042.1415. It just has a single monitor.
I am using Psychtoolbox for a method of constant stimuli task that involves displaying images. A floating adapter image is displayed first for 30 seconds, and then the participant goes through 90 trials. Each trial involves the following: a 2 second blank period showing a black screen and small fixation cross. Then an image (the fixation cross is constantly present) is shown for 0.2 seconds. Then the image disappears, the participant responds with a keypress, and finally, there is a 5 second adaptation period with the same floating adapter image each time. Once the 90th trial is finished, an exit screen is shown, and when the participant presses any key, the Psychtoolbox window closes.
Sometimes the experiment works fine, with all 90 trials completed with no issue. Sometimes, though, unpredictably, MATLAB or Psychtoolbox seems to freeze on one of the last trials. Sometimes it’s the 88th trial, sometimes the 89th, sometimes the 87th; there is no pattern I can discern, and the probability that this error will happen seems to be around 50%.
Anyway, what happens is that after the participant responds with a keypress, the floating adapter image never appears. The screen just remains black, with the fixation cross still in the middle of the screen. The only way to exit that I’ve found is by hitting the “Window” key to bring up the Start Menu and then attempting to close the Psychtoolbox window from the Taskbar. MATLAB itself then quits and has to be restarted. Because of that, there’s no error message left behind.
I saw a very similar issue on this forum that was solved by ensuring that each texture was cleared before a new one was created. I modified my code accordingly, and the experiment actually ran successfully three times in a row (this was remarkable), but then I tried running it a fourth time, and the experiment froze on the 87th trial.
Here is the main function that runs the experiment, along with a couple of smaller functions I wrote that may possibly be relevant.
function drawImage
arguments
image {mustBeNumeric};
location (1,4) double;
window(1,1) double;
end
Screen(‘Close’);
image_texture = Screen(‘MakeTexture’,window,image);
Screen(‘DrawTexture’,window,image_texture,[],location,0);
end
function drawFixationCross
arguments
window (1,1) double;
window_rect (1,4) double;
color double;
arm_length (1,1) double;
line_width (1,1) double;
end
[x_center,y_center] = RectCenter(window_rect);
x_coordinates = [-arm_length arm_length 0 0];
y_coordinates = [0 0 -arm_length arm_length];
coordinates = [x_coordinates;y_coordinates];
Screen(‘DrawLines’,window,coordinates,line_width,color,…
[x_center y_center],0);
end
function RunExperiment
arguments
participant (1,1) string;
object_number (1,1) double;
adapter_view (1,1) string;
end
%% Sync tests
Screen(‘Preference’,‘SkipSyncTests’,0);
%% Load the experiment stimuli and other variables from file
load Variables.mat; %#ok
clear tutorial_text;
%% Extra input argument validation
if participant == “”
error(‘participant cannot be an empty string!’);
elseif object_number < 1 || object_number > length(objects) - 1
error(‘object_number must be a number from 1 to %d!’,…
length(objects) - 1);
elseif adapter_view == “”
error(‘adapter_view cannot be an empty string!’);
end
%% Set the raw data filename
timestamp = sprintf(’%04d-%02d-%02d_%02d-%02d-%02d’,round(clock));
raw_data_filename = sprintf(‘RAW_%s_obj-%d_%s_%s.mat’,…
participant,object_number,adapter_view,timestamp);
%% Get the object’s adapter images and test images
adapter_images = objects(object_number).adapters;
test_images = objects(object_number).test;
if isempty(adapter_images)
error(‘No adapter images found for this object!’);
elseif isempty(test_images)
error(‘No test images found for this object!’);
end
clear objects;
%% Get the size (in pixels) of the images
%{
NOTE: The size function’s output has the dimensions in the wrong order,
so the dimensions have to be switched around.
%}
image_size = size(adapter_images{1});
image_size = [image_size(2) image_size(1)];
%% Calculate the number of times each test image must be presented
max_image_presentations = trial_number / length(test_images);
%% Preallocate arrays to track test image presentations and hold data
tracker = zeros(1,length(test_images));
test_view_data = strings(1,trial_number);
response_data = zeros(1,trial_number);
reaction_time_data = zeros(1,trial_number);
%% Set up Psychtoolbox to display images and text
%{
NOTE: This also involves establishing the boundaries of the floating area
that the adapter and test images will be restricted to.
%}
PsychDefaultSetup(2);
screens = Screen(‘Screens’);
screen_number = min(screens);
black = BlackIndex(screen_number);
white = WhiteIndex(screen_number);
[window,window_rect] = PsychImaging(‘OpenWindow’,screen_number,black);
try
image_rect = [0 0 image_size(1) image_size(2)];
[x_range,y_range] = calculateLocationRange(window_rect,…
floating_area_size,image_size);
Screen(‘TextSize’,window,text_size);
Screen(‘TextFont’,window,‘Courier’);
HideCursor(window);
clear screens screen_number floating_area_size image_size text_size black;
%% Display the start screen
%{
NOTE: 65 and 186 are the key codes for the ‘a’ and ‘;’ keys. These key
codes must be modified if and when the input method is changed.
%}
DrawFormattedText(window,start_screen_text,‘center’,‘center’,white);
Screen(‘Flip’,window);
KbStrokeWait;
clear start_screen_text;
RestrictKeysForKbCheck([65 186]);
%% Initial adaptation period
adapter_index = strcmp(adapter_view,adapter_views);
adapter = adapter_images{adapter_index};
clear adapter_views adapter_images adapter_index;
[location,current_edge] = chooseRandomLocation(image_rect,x_range,y_range);
[target_edge,target_location] = chooseTargetEdge(location,x_range,…
y_range,current_edge);
drawImage(adapter,location,window);
drawFixationCross(window,window_rect,fixation_cross_color,arm_length,…
line_width);
Screen(‘Flip’,window);
seconds_passed = 0;
tic;
while seconds_passed < initial_adaptation_period
[location,arrived] = moveTowardLocation(location,target_location,1);
if arrived
[target_edge,target_location] = chooseTargetEdge(location,…
x_range,y_range,target_edge);
end
drawImage(adapter,location,window);
drawFixationCross(window,window_rect,fixation_cross_color,…
arm_length,line_width);
Screen(‘Flip’,window);
WaitSecs(time_to_travel_one_pixel);
seconds_passed = toc;
end
for i = 1:trial_number
%% Blank period
drawFixationCross(window,window_rect,fixation_cross_color,...
arm_length,line_width);
Screen('Flip',window);
WaitSecs(blank_period);
%% Test period
%{
NOTE: Keeping track of the image that was presented during the previous
trial (previous_test_index) is necessary to prevent the same image
being displayed twice in succession.
%}
image_chosen = false;
while image_chosen == false
test_index = randi(length(test_images));
if i == 1
image_chosen = true;
elseif test_index ~= previous_test_index &&...
tracker(test_index) < max_image_presentations
image_chosen = true;
end
end
previous_test_index = test_index;
tracker(test_index) = tracker(test_index) + 1;
test_view_data(i) = test_views(test_index);
current_test = test_images{test_index};
[location,~] = chooseRandomLocation(image_rect,x_range,y_range);
drawImage(current_test,location,window);
drawFixationCross(window,window_rect,fixation_cross_color,...
arm_length,line_width);
Screen('Flip',window);
WaitSecs(test_period);
%% Response period
%{
NOTE: I inserted a pause of 0.2 seconds because without it, the top_up
adaptation period would start the instant I made my response, and the
speed was actually a little unnerving.
%}
drawFixationCross(window,window_rect,fixation_cross_color,...
arm_length,line_width);
Screen('Flip',window);
response_made = false;
start_time = GetSecs;
while response_made == false
[key_is_pressed,~,key_code] = KbCheck;
if key_is_pressed
response_made = true;
end
end
end_time = GetSecs;
WaitSecs(0.2);
response_data(i) = find(key_code);
reaction_time_data(i) = end_time - start_time;
clc;
%% Save the raw data
saveData(raw_data_filename,participant,object_number,adapter_view,...
timestamp,test_view_data,response_data,reaction_time_data);
%% Top-up adaptation period
if i == trial_number
break;
else
[location,current_edge] = chooseRandomLocation(image_rect,...
x_range,y_range);
[target_edge,target_location] = chooseTargetEdge(location,...
x_range,y_range,current_edge);
drawImage(adapter,location,window);
drawFixationCross(window,window_rect,fixation_cross_color,...
arm_length,line_width);
Screen('Flip',window);
seconds_passed = 0;
tic;
while seconds_passed < top_up_adaptation_period
[location,arrived] = moveTowardLocation(location,...
target_location,1);
if arrived
[target_edge,target_location] = ...
chooseTargetEdge(location,x_range,y_range,target_edge);
end
drawImage(adapter,location,window);
drawFixationCross(window,window_rect,fixation_cross_color,...
arm_length,line_width);
Screen('Flip',window);
WaitSecs(time_to_travel_one_pixel);
seconds_passed = toc;
end
end
Screen('Close');
end
%% Display the exit screen
RestrictKeysForKbCheck([]);
DrawFormattedText(window,exit_screen_text,‘center’,‘center’,white);
Screen(‘Flip’,window);
KbStrokeWait;
Screen(‘Close’);
sca;
sca;
%% Save the raw data
saveData(raw_data_filename,participant,object_number,adapter_view,…
timestamp,test_view_data,response_data,reaction_time_data);
fprintf(‘Filename: %s\n’,raw_data_filename);
clear;
%% Handle errors
catch the_error
save([‘ERROR_’ raw_data_filename])
sca;
sca;
rethrow(the_error);
end
end