matlabgaussianpsychtoolbox

Only a portion of the code is executed and no error message is displayed


I am using MATLAB 2020 Psychtoolbox on Mac OS and everytime I run this code, they screen turns grey followed by an error sound, however, no error message is displayed in the command window. How do I make all the code execute?

% Clear the workspace
close all;
clearvars;
sca;

% Setup PTB with some default values
PsychDefaultSetup(2);

% Seed the random number generator. Here we use the an older way to be
% compatible with older systems. Newer syntax would be rng('shuffle'). Look
% at the help function of rand "help rand" for more information
rand('seed', sum(100 * clock));

  % Set the screen number to the external secondary monitor if there is one
% connected
screenNumber = max(Screen('Screens'));

% Define white, grey and black
white = WhiteIndex(screenNumber);
grey = white / 2;
black = BlackIndex(screenNumber);

% Open an on screen window
[window, windowRect] = PsychImaging('OpenWindow', screenNumber, grey);

% Get the size of the on screen window
[screenXpixels, screenYpixels] = Screen('WindowSize', window);

% Query the frame duration
ifi = Screen('GetFlipInterval', window);

% Set up alpha-blending for smooth (anti-aliased) lines
Screen('BlendFunction', window, 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA');

% Setup the text type for the window
Screen('TextFont', window, 'Ariel');
Screen('TextSize', window, 36);

% Get the centre coordinate of the window
[xCenter, yCenter] = RectCenter(windowRect);


%----------------------------------------------------------------------
%                       Keyboard information
%----------------------------------------------------------------------

% Define the keyboard keys that are listened for. We will be using the left
% and right arrow keys as response keys for the task and the escape key as
% a exit/reset key
escapeKey = KbName('ESCAPE');
leftKey = KbName('LeftArrow');
rightKey = KbName('RightArrow');
downKey = KbName('DownArrow');

%----------------------------------------------------------------------
%                       Fixation cross
%----------------------------------------------------------------------

% Here we set the size of the arms of our fixation cross
fixCrossDimPix = 10;

% Now we set the coordinates (these are all relative to zero we will let
% the drawing routine center the cross in the center of our monitor for us)
xCoords = [-fixCrossDimPix fixCrossDimPix 0 0];
yCoords = [0 0 -fixCrossDimPix fixCrossDimPix];
allCoords = [xCoords; yCoords];

% Set the line width for our fixation cross
lineWidthPix = 4;

%----------------------------------------------------------------------
%                            Colors
%----------------------------------------------------------------------

% We are going to use three colors for this demo. Red, Green and blue.
wordList = {'Green', 'Magenta', 'Orange'};
Colors = [0 1 0; 1 0 1; 0.8500 0.3250 0.0980];

%----------------------------------------------------------------------
%                  Define positions of sequences
%----------------------------------------------------------------------

leftX = screenXpixels/2.5;
leftY = screenXpixels/1.6;
rightX = screenXpixels/1.7;
rightY = screenYpixels/1.6;
upX = screenXpixels/2.1;
upY = screenYpixels/2.6;

left = [leftX leftY];
right = [rightX rightY];
up = [upX upY];

%----------------------------------------------------------------------
%                  Randomise temporal order of trials
%----------------------------------------------------------------------
 
trialorder = [1 0 0 0 0];
randtemp = shuffle(trialorder);

%----------------------------------------------------------------------
%                           Trial loop
%----------------------------------------------------------------------
nTrials = 5;

for trial = 1:randtemp
    
    % randomise position of sequences
    randpos = shuffle(left, right, up);
    
    % fixation cross
    % Draw the fixation cross in white, set it to the center of our screen and
    % set good quality antialiasing
    Screen('DrawLines', window, allCoords,...
    lineWidthPix, white, [xCenter yCenter], 2);

    % Derive distributions
    seq1 = distribution(0.02, 0.126, 0.146, 0.106, 5); % high variance
    seq2 = distribution(0.02, 0.126, 0.146, 0.106, 5); % low variance
    seq3 = distribution(0.02, 0.126, 0.146, 0.106, 5); % low variance
    
    seq4 = distribution(0.02, 0.126, 0.146, 0.106, 5);
    seq5 = distribution(0.02, 0.126, 0.146, 0.106, 5);
    seq6 = distribution(0.02, 0.126, 0.146, 0.106, 5);
    
    seq7 = distribution(0.02, 0.126, 0.146, 0.106, 5);
    seq8 = distribution(0.02, 0.126, 0.146, 0.106, 5);
    seq9 = distribution(0.02, 0.126, 0.146, 0.106, 5);
    
    seq10 = distribution(0.02, 0.126, 0.146, 0.106, 5);
    seq11 = distribution(0.02, 0.126, 0.146, 0.106, 5);
    seq12 = distribution(0.02, 0.126, 0.146, 0.106, 5);
    
    seq13 = distribution(0.02, 0.126, 0.146, 0.106, 5);
    seq14 = distribution(0.02, 0.126, 0.146, 0.106, 5);
    seq15 = distribution(0.02, 0.126, 0.146, 0.106, 5);

    if trial == 1 
       DrawFormattedText(window, 'Name the color \n\n Press Any Key To Begin',...
       'center', 'center', black);
       Screen('Flip', window);
       KbStrokeWait;
    end
    
    if randtemp() == 0
        % trail 1
        Screen('DrawText', num2str(seq1), white, randpos(1));
        Screen('DrawText', num2str(seq2), white, randpos(2));
        Screen('DrawText', num2str(seq3), white, randpos(3));
        WaitSecs(0.75)
        Screen('Flip', window);
        KbStrokeWait;
           
        Screen('DrawText', num2str(seq2), white, randpos(1));
        Screen('DrawText', num2str(seq3), white, randpos(2));
        WaitSecs(0.75)
        Screen('Flip', window);
        KbStrokeWait;
        
        %trial 2
        %repeat
        
    else 
        Screen('DrawText', num2str(seq13), white, randpos(1));
        Screen('DrawText', num2str(seq14), white, randpos(2));
        Screen('DrawText', num2str(seq15), white, randpos(3));
        WaitSecs(0.75)
        Screen('Flip', window);
        KbStrokeWait;
           
        Screen('DrawText', num2str(seq13), white, randpos(1));
        Screen('DrawText', num2str(seq14), white, randpos(2));
        WaitSecs(0.75)
        Screen('Flip', window);
        KbStrokeWait;
    end
end       

        

      

% Flip to the screen
Screen('Flip', window);

% Wait for a key press
KbStrokeWait;

% Clear the screen
sca

The 'distribution' function is a self-made function that generates a Gaussian distribution of random numbers with a specified mean, variance, upper limit, lower limit and a given amount of numbers:

function distribution(va, mu, ul, ll, nvals)
 multiplier=10;
 x = mu + randi(multiplier*nvals,1)*sqrt(va); % Generate sufficient random numbers
 idx = (ll <= x) & (x <= ul); % Extract the value in the given range [min max]
 while sum(idx)<nvals
    multiplier=multiplier+1;
    x = mu + randi(multiplier*nvals,1)*sqrt(va); % Generate sufficient random numbers
    idx = (ll <= x) & (x <= ul); % Extract the value in the given range [min max]
 end
 x = x(idx);
 x = x(1:nvals); % Extract numbers

Solution

  • You're only seeing the grey screen because the error doesn't cause the Psychtoolbox window (which you have set to have a grey background) to close. To have the screen close and display the error, wrap your code in a try, catch statement, which will close the screen and rethrow an error, if encountered.

    For example (here the word CODE is just a placeholder, instead replace it with your actual code)

    try
        CODE
    catch e
        sca;
        rethrow(e)
    end
    

    In this case, if an error is encountered within the body of the try statement, it will go to the catch statement, calling the error e. First the screen will be closed with sca, then the error will be actually shown, via rethrow.

    In terms of the actual error you were encountering, I think there are at least few issues with your current code:

    1. The Shuffle function in Psychtoolbox is capitalized - 'Shuffle' and has a single input. Here, you're using 'shuffle', and providing three separate inputs.

      Instead of providing 'left', 'right' and 'up' as separate inputs, combined them into a elements of a single cell array:

      replacing: randpos = shuffle(left, right, up);

      with: randpos = Shuffle({left, right, up});

      and select them as elements of a cell array:

      replacing: Screen('DrawText', num2str(seq1), white, randpos(1));

      with: Screen('DrawText', window, num2str(seq1), white, [], black, randpos{1}(1), randpos{1}(2));

    2. In the distribution function you have defined, you haven't included an output argument. Replace your current first function line with: function x = distribution(va, mu, ul, ll, nvals)

    3. KbStrokeWait without an input parameter only checks the first keyboard attached. This may be ignoring keypresses if you are using an external keyboard on a laptop, for example. Using KbStrokeWait(-3) will check all attached devices.

    4. Your distribution function seems to either not be converging on a solution, or taking a long time to identify a solution, since it seems to be randomly generating values and then checking that is has enough in your desired interval. I would instead start with the built function to generate random normal values. For example the following will generate 5 values from a distribution with a mean of 0.02 and a variance of 0.126. It doesn't implement checking that all the generated values are within a given range, though: randn(1, 5) * sqrt(0.126) + 0.02;

    5. You're missing the window pointer in the call to DrawText.

    There may be other issues as well, but addressing these will get you started.