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