Visual Operant MATLAB code
NOTE: you must have installed Psychophysics Toolbox
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function gratingStim_square_clay(tempfreq,spfreq,sduration,iduration,nsessions)
%gratingStim_square(1,0.035,2,5,1)
datestr = date;
savefile = [datestr '_'];
[fnm pnm] = uiputfile('*.mat','Save File A..',savefile);
lum_center = 128;
AssertOpenGL; % Make sure this is running on OpenGL Psychtoolbox:
screenid = max(Screen('Screens')); % Choose screen with maximum id - the secondary display on a dual-display setup for display
x = ((0:255).^(1/2.2))'; % gamma correction
table = repmat(x/max(x),1,3);
Screen('LoadNormalizedGammaTable',screenid,table);
resolution = Screen('Resolution', screenid);
resheight = resolution.height;
reswidth = resolution.width;
stimwidth = 15*(resolution.width/16); %full field (with 1/16 of the screen blank for the diode)
stimheight = resolution.height;
stimwindow = [stimwidth stimheight];
spfreq_new = spfreq/(.2618*reswidth/(40.64)); % 40.64 is the screen width in cm
rotateMode = kPsychUseTextureMatrixForRotation;
angles = [0 45 90 135 180 225 270 315];
contrasts = [0.16 0.32 0.64 1]; %[0.08 0.16 0.32 0.64 0.8 1];
all_combs = combn(1:max([length(angles),length(contrasts)]),2);
all_combs(length(contrasts)*length(angles)+1:end,:) = [];
if length(angles) > length(contrasts)
all_combs = fliplr(all_combs);
end
comb_all_sessions = zeros(size(all_combs,1),nsessions);
for i = 1:nsessions
comb_all_sessions(:,i) = randperm(length(contrasts)*length(angles))';
end
amplitude = .5;
phase = 0; % Phase is the phase shift in degrees (0-360 etc.) applied to the sine grating:
win = Screen('OpenWindow', screenid, lum_center); % Open a fullscreen onscreen window on that display, choose a background color of 128 = gray, i.e. 50% max intensity
AssertGLSL; % Make sure the GLSL shading language is supported
ifi = Screen('GetFlipInterval', win, lum_center); % Retrieve video redraw interval for later control of our animation timing
phaseincrement = (tempfreq * 360) * ifi; % Compute increment of phase shift per redraw
diodeBox = 25; % size of the diode box
offset = lum_center/255;
Screen('FillRect', win, lum_center);
Screen('Flip', win);
%% clay:
rewOri = 90; % degree orientation for rewarded visual stimulus
arData = 0; % initialize data from Arduino
% set up text file for event text output
[txtFilename, txtFilePath] = uiputfile('*.txt');
serTxtFile = fopen(txtFilename, 'a'); % set to append new events during sess
% set up serial communication with arduino
% NOTE: you must determine the COM port for the arduino from windows device
% manager or arduino IDE
arduino=serial('COM22','BaudRate',9600); % create serial communication object on arduino port
fopen(arduino); % initiate arduino communication
pause(3); % wait a few sec for Arduino to initiate
%%
tic
tSessStart = tic; % clay put in to time serial events during session
while (toc<=5) % wait 50 seconds for the screen to adjust
tim = toc;
[keyIsDown,secs,keyCode] = KbCheck;
if keyCode(27); break; end
end
sequence = nan(nsessions*length(angles)*length(contrasts),2); %initialize the sequence array
abort = 0; count = 0;
for i = 1:nsessions % loop over sessions (= trials)
disp(['Session ',int2str(i),'/',int2str(nsessions)])
for j = 1:size(comb_all_sessions,1) % loop over orientations
count = count+1;
ori = angles(all_combs(comb_all_sessions(j,i),1));
con = contrasts(all_combs(comb_all_sessions(j,i),2));
sequence(count,1) = ori;
sequence(count,2) = con;
%% use this if you want to check for response during vis stim
% %% serial output to Arduino (whether trial is rewarded)
% if ori == rewOri
% fprintf(arduino,'%s',char('1')); % send answer variable content to arduino
% else
% fprintf(arduino,'%s',char('2'));
% end
%
%%
gratingtex = CreateProceduralSineSquareGrating(win, stimwindow(1), stimwindow(2), offset*[1,1,1,0], [], con);
Screen('FillRect', win, lum_center);
Screen('Flip', win);
%% wait for serial from Arduino to start trial ?
% something like:
% if Serial.available(arduino)
%%
% commenting out ITI to wait for arduino to initiate trial
% tic
% while (toc<=iduration) % this is the ITI (iduration)
% tim = toc;
% end
%% Start visual stimulus
fprintf(serTxtFile, '%s', 'trial start');
fprintf(serTxtFile, '%f', toc(tSessStart));
[keyIsDown,secs,keyCode] = KbCheck;
if keyCode(27); abort = 1; break; end
tim = Screen('Flip', win);
vblStime = tim + sduration;
while (tim<vblStime) % this is the actual visual stim
phase = phase + phaseincrement; % Increment phase by 1 degree
Screen('DrawTexture', win, gratingtex, [], [1 1 stimwidth stimheight], ori, [], [], [], [], rotateMode, [phase, spfreq_new, amplitude, 0]);
Screen('FillRect', win, [255 255 255], [reswidth-diodeBox resheight-diodeBox reswidth resheight]); %show the diode box in white
tim = Screen('Flip', win, tim + 0.5 * ifi); % Show it at next retrace
% insert serial input to elongate trial ("vblStime") if rew or
% pun, and write mouse response to text file
% fscanf(s, 'or read something from arduino (all events and arduino times');
end % END stimulus presentation
%% serial output to Arduino (whether trial is rewarded)
% to initiate lick/response detection
if ori == rewOri
fprintf(arduino,'%s',char('1')); % send '1' if current ori = rewOri
else
fprintf(arduino,'%s',char('2')); % or send '2' if not
end
%% now wait for response from Arduino to initiate new trial
while arData == 0
% look for arduino serial data (upon response or trialDur)
if arduino.BytesAvailable > 0
evTime = toc(tSessStart);
arData = fscanf(arduino); % read arduino output
%disp('data comes back');
%disp(arData);
arData = str2double(arData); % change to num
% print trial outcome to file
switch arData
case 0 % if animal doesn't respond
fprintf(serTxtFile, '%s', 'trial over');
fprintf(serTxtFile, '%f', evTime);
case 1 % if animal gets it right (rew)
fprintf(serTxtFile, '%s', 'reward');
fprintf(serTxtFile, '%f', evTime);
case 2 % if animal gets it wrong (pun)
fprintf(serTxtFile, '%s', 'punishment');
fprintf(serTxtFile, '%f', evTime);
end
end
% include keyboard break if desired
[keyIsDown,secs,keyCode] = KbCheck;
if keyCode(27); abort = 1; break; end
end
arData = 0;
%%
[keyIsDown,secs,keyCode] = KbCheck;
if keyCode(27); abort = 1; break; end
end
if abort==1 ; break ; end
end
% Close the window. This will also release all other ressources:
Screen('CloseAll');
parameters.spfreq = spfreq;
parameters.tempfreq = tempfreq;
parameters.sduration = sduration;
parameters.iduration = iduration;
parameters.nsessions = nsessions;
parameters.sequence = sequence;
savefile = strcat(pnm,fnm);
save(savefile,'parameters');
fclose(arduino); % close serial connection with Arduino
fclose(serTxtFile);
return;