function [Stim]=rdm_stimulus(coh)
%
% rdm_stimulus :: Function that generates the random dot motion stimuli
%
%% Variables
% coh :: Coherence level of the trial (range is [0 1])
%
% Stim :: Random dot motion stimulus (3D matrix: 2 spatial dimensions and 1
% temporal) (Scale of pixel [luminance] intensities is 0-255)
%
%% Reference
% Grossberg, S. and Pilly, P. K. (2008). Temporal dyanamics of decision-making during motion perception in the visual cortex. Vision Research, 48(12), 1345-1373.
%
%% Author
% Praveen K. Pilly (advaitp@gmail.com)
%
%% License policy
% Written by Praveen K. Pilly, Department of Cognitive and Neural Systems, Boston University
% Copyright 2009, Trustees of Boston University
%
% Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted
% without fee, provided that the above copyright notice and this permission notice appear in all copies, derivative works and
% associated documentation, and that neither the name of Boston University nor that of the author(s) be used in advertising or
% publicity pertaining to the distribution or sale of the software without specific, prior written permission. Neither Boston
% University nor its agents make any representations about the suitability of this software for any purpose. It is provided "as
% is" without warranty of any kind, either express or implied. Neither Boston University nor the author indemnify any
% infringement of copyright, patent, trademark, or trade secret resulting from the use, modification, distribution or sale of
% this software.
%
%% Last modified
% June 25, 2009
%%
% 3 uncorrelated random dot motion sequences are generated and then
% frames from each are interleaved to form the stimulus
% In each of the 3 constituent motion sequences, from one frame to the next
% a fixed fraction of dots, namely the coherence level, are randomly
% chosen to move in the signal direction while the remaining dots are
% given random positions within the grid
% The probability for a dot to be chosen as signal for continuous frames
% depends on the coherence level
% To set the pseudo-random number generator to a random state to begin with
rand('state',sum(100*clock))
randn('state',sum(100*clock))
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% For simplicity, the signal dots are displaced in the rightward direction
% by 1 pixel in each jump
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Specification of the signal direction (3 refers to 0 deg)
dir=3; % one of 8 directions
% Dimension of stimulus grid, which is for convenience chosen to be a square
grid=60;
% Number of dots in each frame
Ndots=100;
% Number of frames in each of the constituent motion sequences
Nfs=75;
theta=(dir-1)*pi/4; % direction in radians
x=cos(theta);
y=sin(theta);
if abs(x)<10^(-15)
x=0;
end
if abs(y)<10^(-15)
y=0;
end
% Spatial displacement between two consecutive signal dot flashes
Dx=sign(x);
Dy=sign(y);
Nsignal=ceil(coh*Ndots); % Number of signal dots chosen from each frame to
% the next
% Initialization of pre-stimulus
preI=zeros(grid,grid,Nfs,3);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Main loop
%
% I do not think this is the best implementation for a random dot motion
% stimulus. Check out http://www.shadlen.org/matlab/mfiles/vcrdm.htm for a
% more efficient, generic implementation, which I have loved to use in my
% various psychophysical experiments
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for seq=1:3 % one of 3 uncorrelated sequences
for fr=1:Nfs % one of the frames
if fr==1
I=zeros(grid);
nS=0;
S=[];
for i=1:Ndots
X=find(I==0);
Y=randperm(grid^2-i+1-nS);
d=X(Y(1));
I(d)=1;
Sd=shroud(d,grid);
S=unique([S Sd]);
nS=size(S,2);
I(Sd)=-1;
end
I(S)=0;
preI(:,:,fr,seq)=I;
Dpos=find(I)';
end
if fr>1
I=zeros(grid);
nS=0;
S=[];
s1=[];s2=[];s3=[];s4=[];
if Nsignal>0
Y=randperm(Ndots);
T=Dpos(Y(1:Nsignal));
T1=modD(T,grid);
T2=(T-T1)/grid+1;
% Signal dot displacements
T1=T1+Dx;
T2=T2+Dy;
% If any signal dot is displaced outside the grid, it is
% wrapped around to appear from the opposite side
for j=1:Nsignal
if ~((T1(j)<1)|(T1(j)>grid)|(T2(j)<1)|(T2(j)>grid))
s3=[s3 T1(j)];
s4=[s4 T2(j)];
else
s1=[s1 modD(T1(j),grid)];
s2=[s2 modD(T2(j),grid)];
end
end
T=grid*(s4-1)+s3;
T12=grid*(s2-1)+s1;
S=shroud(T,grid);
I(T)=1;
I(S)=-1;
nS=size(S,2);
if size(s3,2)~=Nsignal
for i=1:Nsignal-size(s3,2)
if I(T12(i))==0
d=T12(i);
else
X=find(I==0);
Y=randperm(grid^2-i+1-nS-size(s3,2));
d=X(Y(1));
end
I(d)=1;
Sd=shroud(d,grid);
I(Sd)=-1;
S=unique([S Sd]);
nS=size(S,2);
end
end
end
% Noise dots are given random positions within the grid
if Ndots-Nsignal>0
for i=1:Ndots-Nsignal
X=find(I==0);
Y=randperm(grid^2-i+1-nS-Nsignal);
d=X(Y(1));
I(d)=1;
Sd=shroud(d,grid);
I(Sd)=-1;
S=unique([S Sd]);
nS=size(S,2);
end
end
I(S)=0;
preI(:,:,fr,seq)=I;
Dpos=find(I)';
end
end
end
Stim=zeros(grid,grid,3*Nfs);
% Assembling the main stimulus
for fr=1:Nfs
for seq=1:3
Stim(:,:,3*(fr-1)+seq)=preI(:,:,fr,seq);
end
end
for fr=1:3*Nfs
imshow(Stim(:,:,fr))
end
close all
return