Random Dot Motion Task - Animation Problem

Hi All,

 

I hope this finds you well. I was wondering of anyone could help me with the following problem. Using the script below (I tried to only post the necessary bits) on a Mac with Matlab 2017b and the latest Psychtoolbox, I am experiencing some problems creating a cloud of random dot motions: a) It seems that the cloud of dots flicker a lot and b) quite a few (more that 7%) of the flips are missed.

 

Is there any way to improve the animation of the random dots? So far we tried different values for the speed of the dots and coherence levels with no effect on the animation of the dots. On my old MacBook Pro the problem seems to be less of a problem, e.g. the dots do not flicker as much and the number of missed flips is reduced (still around 9% misses though). I guess it might be a graphic card problem? 

 

Thanks for any help and all the best!

 

Hans  

 

% -------------------------------------------------------------------------

%         Psychtoolbox Setup & Stimulus and Response Parameters

% -------------------------------------------------------------------------

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

 

screens                 = Screen('Screens'); % obtain screen numbers

screenNumber      = max(screens); % use main screen

 [w, wrect]             = PsychImaging('OpenWindow', screenNumber,...

                                 0 , [], 32, 2,[], [],  kPsychNeed32BPCFloat);

[x_0, y_0]              = RectCenter(wrect);

M                          = [-pi/2 pi/2]; % motion direction

P                          =  [(x_0-250) (x_0+250)];

col                        =  [0;   0;  255] ;% dot color (blue at the moment)

waitframes           = 1; % number of frames to wait

stimdur                 = 2; % stimulus duration in seconds

iti                          = 1; % intertrial interval; activate if this needs to be constant

fps                        = 60; % framerate in frames per second

nfram                   = stimdur*fps; % stimulus  duration in number of frames 

mowi                    = 30; % monitor width

viewdist                = 60; % viewing distance

dotspeed              = 5; % dot speed in visual degrees per second

ndots                    = 200; % number of dots

max_d                  = 2; % maximum radius of aperture in degrees

coherence            = [0.30 0.85]; % coherence level for all stimuli

white                    = [255; 255; 255]; % white color 

ppd                      = pi*(wrect(3)-wrect(1))/atan(mowi/viewdist/2)/360; % pixels per degree

pfs                       = dotspeed*ppd/fps; % dot speed  in pixels per frame

fix_cord               = [[x_0, y_0]-fix_r*ppd [x_0, y_0]+fix_r*ppd]; % fixation cross coordinates

rmax                    = max_d*ppd; % maximum radius of annulus (pixels from center)

s                          = 2; % dot size in pixels

rkeys                   = [25 17]; % response keys rkeys(1) = v, rkeys(2) = n

ifi                         = Screen('GetFlipInterval', w); % flip interval

vbl                       = Screen('Flip', w); % flip

  

 % ---------------------------------------------------------------------

 %                  Random Dot Kinematogram Creation

 % ---------------------------------------------------------------------

   

rdk         = NaN(ndots,2,nfram); % dot Cartesian coordinates array 

% stimulus parameters

nsdots      = floor(coh*ndots)                                          ; % number of signal dots

nndots      = ndots - nsdots                                            ; % number of noise  dots

 

% initialize dot positions

   

for t = 1:3

        r = rmax*sqrt(rand(ndots,1)); % radius  polar coordinates

        phi = 2*pi*rand(ndots,1); % phi polar coordinates

        cs              = [cos(phi) sin(phi)]; % transformation to Cartesian coordinates

        xy              = [r r].*cs; % dot positions in Cartesian coordinates (pixels from center)

        rdk(:,:,t)      = xy;

    end

 

% cycle over remaining frames in triades

for t = 4:3:nfram

 

   % cycle over dot streams

     for f = 1:3

 

 % signal and noise dots

 % -------------------------------------------------------------

dxdy            = NaN(ndots,2); % initialize dot displacement 

sidx            = sort(randsample(ndots,nsdots)); % sample signal dot indices

dxdy(sidx,:)    = repmat(pfs*[cos(sdphi) sin(sdphi)],nsdots,1)  ; % dot position change vector

ndphi           = 2*pi*rand(nndots,1); % phi polar coordinates   

nidx            = setxor(sidx,1:ndots); % determine   noise  dot indices

dxdy(nidx,:)    = pfs*[cos(ndphi) sin(ndphi)]; % dot position change vector

            rdk(:,:,t+f-1)  = rdk(:,:,t-4+f) + dxdy; % update RDK

 

% circular aperture and dot relocation 

% ---------------------------------------------------------

out = find(sqrt(rdk(:,1,t+f-1).^2 + rdk(:,2,t+f-1).^2) > rmax);

     if out

 

    nout = length(out); % number of dots to replace

    % cycle over dots to replace

                for i = 1:nout

 

                    p   =  rdk(out(i),:,t-4+f) + [pos y_0]; % dot motion line support vector 

                    u   =  dxdy(out(i),:); % dot motion line direction vector

                    a   = -u(2); % dot motion line in coordinate form ax + by = c

                    b   =  u(1); % dot motion line in coordinate form ax + by = c

                    c   =  p(1)*a + p(2)*b; % dot motion line in coordinate form ax + by = c

                    d   = c - a*pos - b*y_0; % re-centered system

 

                    % check for two intersection points

                    if rmax^2*(a^2 + b^2) >= d^2      

 

                        % evaluate dot motion aperture intersection points

                        isp = [pos+((a*d+b*sqrt(rmax^2*(a^2 + b^2)-d^2))/(a^2+b^2)), ...  

                               y_0+((b*d-a*sqrt(rmax^2*(a^2 + b^2)-d^2))/(a^2+b^2)); ...

                               pos+((a*d-b*sqrt(rmax^2*(a^2 + b^2)-d^2))/(a^2+b^2)), ...                    

                               y_0+((b*d+a*sqrt(rmax^2*(a^2 + b^2)-d^2))/(a^2+b^2))];

 

                        % intersection point - support point distances

                        [mval,mi] = min([norm(isp(1,:) - p) norm(isp(2,:) - p)]);

 

 

                   % relocate dot to opposite aperture side retaining identical motion 

                  p_new   = isp(setxor(mi,[1 2]),:) + (rdk(out(i),:,t+f-1) + [pos y_0]) - isp(mi,:);

 

                    end

 

                    % replace dot coordinates

                    rdk(out(i),:,t+f-1) = p_new - [pos y_0];

                end

            end

        end

    end

 

% -----------------------------------------------------------------

% Observation : Random Dot Kinematogram

% -----------------------------------------------------------------

 

  

    for i = 1:nfram

        if (i>1)

            Screen('FillOval', w, uint8(white), fix_cord); % draw fixation dot (flip erases it)

            Screen('DrawDots', w, rdk(:,:,i)', s, col, [pos y_0], 1); % determine dot color  

            Screen('DrawingFinished', w);

        end

        

        vbl = Screen('Flip', w, vbl + (waitframes-0.5)*ifi); % flip screen

        

        a_t     = NaN; % default action

        RT      = NaN;

        

        [keyIsDown, keySecs, keyCode]  = KbCheck;

        

            if keyIsDown

 

             % if the pressed key is a response key

             if find(keyCode) == rkeys(1) || find(keyCode) == rkeys(2)

 

                % distinguish key presses

                if find(keyCode) == rkeys(1)

                    a_t = 1;

                elseif find(keyCode) == rkeys(2)

                    a_t = 2;

                end

 

                % evaluate reaction time

                RT = keySecs - rstart; 

 

             end

            end                   

            

       if a_t == 1  || a_t == 2 % break out of stimuli animation if a response was given

           

   

           break

           

       end

       

    end