Skip to content
Snippets Groups Projects
currentTrial.m 6.18 KiB
Newer Older
veitsupateit's avatar
veitsupateit committed
function [mouse_x, mouse_y, fix_x, fix_y] = currentTrial(img, delay, filter, w, wRect, screenNumber, backgroundcolor)
veitsupateit's avatar
veitsupateit committed
try
    % Setup default aperture size.
veitsupateit's avatar
veitsupateit committed
    ms = 200;
veitsupateit's avatar
veitsupateit committed
    
    % Fovea contains filtered image
    foveaimage = filterImage(img, filter);
    
    % Periphery contains original image
    peripheryimage = img;
    
    % Build texture for fovea
veitsupateit's avatar
veitsupateit committed
    foveatex = Screen('MakeTexture', w, foveaimage);
    tRect = Screen('Rect', foveatex);
veitsupateit's avatar
veitsupateit committed
    
    % Build texture for periphery
veitsupateit's avatar
veitsupateit committed
    nonfoveatex = Screen('MakeTexture', w, peripheryimage);
    [ctRect, dx, dy] = CenterRect(tRect, wRect);
veitsupateit's avatar
veitsupateit committed
    
    % Set cursor to center and hide it
veitsupateit's avatar
veitsupateit committed
    [a, b] = RectCenter(wRect);
    SetMouse(a, b, screenNumber);
veitsupateit's avatar
veitsupateit committed
    HideCursor;
    buttons = 0;
    
    % Make this program important
veitsupateit's avatar
veitsupateit committed
    priorityLevel=MaxPriority(w);
    Priority(priorityLevel);
veitsupateit's avatar
veitsupateit committed
    
    % Wait until all keys on keyboard are released:
    KbReleaseWait;
    
    % Init old mouse position
veitsupateit's avatar
veitsupateit committed
    mxold = 0;
    myold = 0;
veitsupateit's avatar
veitsupateit committed
    
veitsupateit's avatar
veitsupateit committed
    % Create luminance and alpha matrix as a mask to blend the filtered and
    % the original image into each other
veitsupateit's avatar
veitsupateit committed
    [x, y] = meshgrid(-ms:ms, -ms:ms);
veitsupateit's avatar
veitsupateit committed
    maskblob = ones(2*ms+1, 2*ms+1, 2);
    
veitsupateit's avatar
veitsupateit committed
    % Fill alpha layer with gaussian
veitsupateit's avatar
veitsupateit committed
    xsd = ms / 2.2;
    ysd = ms / 2.2;
veitsupateit's avatar
veitsupateit committed
    maskblob(:, :, 2) = 1 - exp(-((x / xsd).^2)-((y / ysd).^2));
veitsupateit's avatar
veitsupateit committed
    
    % Build a single transparency mask texture:
    masktex = Screen('MakeTexture', w, maskblob);
    
    % Show image
    imageTexture = Screen('MakeTexture', w, img);
    Screen('DrawTexture', w, imageTexture);
veitsupateit's avatar
veitsupateit committed
    
    % Get timestamp of first show
    t0 = Screen('Flip', w);
veitsupateit's avatar
veitsupateit committed
    
    % Init stillTime. stillTime is used to measure the time without
    % movement > distance threshold
    stillTime = 0;
    
    % Init vectors for mouse coordinates
    mouse_x = [];
    mouse_y = [];
    
    % Init vectors for fixation point coordinates
    fix_x = [];
    fix_y = [];
    
veitsupateit's avatar
veitsupateit committed
    % Init flag. If we already have an image blurred at the fixation
veitsupateit's avatar
veitsupateit committed
    % point, we only want to redraw it if there is a movement > distance
    % threshold. Otherwise, we want to stay the blur in place to record
veitsupateit's avatar
veitsupateit committed
    % seccadic movements.
    isFiltered = 0;

veitsupateit's avatar
veitsupateit committed
    while 1
        % Query current mouse cursor position
veitsupateit's avatar
veitsupateit committed
        [mx, my, buttons] = GetMouse;
veitsupateit's avatar
veitsupateit committed
        
        % Record mouse coordinates
        mouse_x(end+1) = mx;
        mouse_y(end+1) = my;
        
        % Calculate euclidean distance between old and new position
veitsupateit's avatar
veitsupateit committed
        dist = eDist(mxold, myold, mx, my);
veitsupateit's avatar
veitsupateit committed
        
veitsupateit's avatar
veitsupateit committed
        % We only want "big" movements to be considered a change of fixation
veitsupateit's avatar
veitsupateit committed
        % point. Smaller movements will be recorded as seccadic
        if dist > 15
veitsupateit's avatar
veitsupateit committed
            stillTime = 0;
veitsupateit's avatar
veitsupateit committed
            % Check if already filtered
            isFiltered = 0;
            
            % Clear everything
            Screen('BlendFunction', w, GL_ONE, GL_ZERO, [1, 1, 1, 1]);
            Screen('FillRect', w, backgroundcolor);
            
            % Draw
            Screen('DrawTexture', w, nonfoveatex, [], ctRect);
            
            % Flip
            t0Still = Screen('Flip', w);
veitsupateit's avatar
veitsupateit committed
        else
veitsupateit's avatar
veitsupateit committed
            % Check if we already exceeded delay
            tStill = GetSecs() - t0Still;
            if tStill >= delay && isFiltered == 0
                
                % Set flag
                isFiltered = 1;
                
                % Append coordinates
veitsupateit's avatar
veitsupateit committed
                fix_x(end+1) = mx;
                fix_y(end+1) = my;
veitsupateit's avatar
veitsupateit committed
                
                % Define area to be filtered
veitsupateit's avatar
veitsupateit committed
                myrect = [mx - ms, my - ms, mx + ms + 1, my + ms + 1];
veitsupateit's avatar
veitsupateit committed
                
                % Clip accordingly
veitsupateit's avatar
veitsupateit committed
                dRect = ClipRect(myrect, ctRect);
                sRect = OffsetRect(dRect, -dx, -dy);
veitsupateit's avatar
veitsupateit committed
                
veitsupateit's avatar
veitsupateit committed
                % Valid destination?
veitsupateit's avatar
veitsupateit committed
                if ~IsEmptyRect(dRect)
veitsupateit's avatar
veitsupateit committed
                    % Draw alpha mask. Opacity is zero at the center of our
                    % aperture. It increases according to the gaussian
                    % function until it reaches 1 (full opacity)

                    % Clear everything to background color, not using
                    % blending [1, 1, 1, 1] means RGBA channels.
veitsupateit's avatar
veitsupateit committed
                    Screen('BlendFunction', w, GL_ONE, GL_ZERO, [1, 1, 1, 1]);
veitsupateit's avatar
veitsupateit committed
                    Screen('FillRect', w, backgroundcolor);
                    
veitsupateit's avatar
veitsupateit committed
                    % Still no blending, draw mask into alpha channel.
veitsupateit's avatar
veitsupateit committed
                    Screen('BlendFunction', w, GL_ONE, GL_ZERO, [0, 0, 0, 1]);
veitsupateit's avatar
veitsupateit committed
                    Screen('DrawTexture', w, masktex, [], myrect);
                    
veitsupateit's avatar
veitsupateit committed
                    % Draw non filtered image. It is drawn according to the
                    % alpha value (GL_DST_ALPHA constant). Alpha mask is
                    % not modified because now we only write to RGB
                    % [1,1,1,0]
veitsupateit's avatar
veitsupateit committed
                    Screen('BlendFunction', w, GL_DST_ALPHA, GL_ZERO, [1, 1, 1, 0]);
veitsupateit's avatar
veitsupateit committed
                    Screen('DrawTexture', w, nonfoveatex, [], ctRect);
veitsupateit's avatar
veitsupateit committed
                    
                    % Draw filtered image, but with inverted alpha value,
                    % meaning that we draw where we did not draw before
                    % (GL_ONE_MINUS_DST_ALPHA constant). Again only write
                    % to RGB.
veitsupateit's avatar
veitsupateit committed
                    Screen('BlendFunction', w, GL_ONE_MINUS_DST_ALPHA, GL_ONE, [1, 1, 1, 0]);
veitsupateit's avatar
veitsupateit committed
                    Screen('DrawTexture', w, foveatex, sRect, dRect);
veitsupateit's avatar
veitsupateit committed
                    
                    % Display
veitsupateit's avatar
veitsupateit committed
                    Screen('Flip', w);
                end
            end
        end
veitsupateit's avatar
veitsupateit committed
        % Keep track of last eye position:
veitsupateit's avatar
veitsupateit committed
        mxold = mx;
        myold = my;
veitsupateit's avatar
veitsupateit committed
        
        % We wait 1 ms each loop-iteration so that we
        % don't overload the system in realtime-priority:
        WaitSecs('YieldSecs', 0.001);
        
veitsupateit's avatar
veitsupateit committed
        % Break if time elapsed from first display is >= 5.
        if GetSecs() - t0 >= 5.0
            break;
        end
veitsupateit's avatar
veitsupateit committed
        % Abort keypress or mouse-click
veitsupateit's avatar
veitsupateit committed
        if KbCheck | find(buttons)
            break;
        end
    end
    
catch
veitsupateit's avatar
veitsupateit committed
    % Recover from exception
veitsupateit's avatar
veitsupateit committed
    sca;
    ShowCursor;
    Priority(0);
    psychrethrow(psychlasterror);
veitsupateit's avatar
veitsupateit committed

%try..catch..
end 
veitsupateit's avatar
veitsupateit committed

veitsupateit's avatar
veitsupateit committed
% Close textures so they do not linger in memory
Screen('Close', foveatex);
Screen('Close', nonfoveatex);
Screen('Close', masktex);
veitsupateit's avatar
veitsupateit committed
return;

veitsupateit's avatar
veitsupateit committed
end