top of page

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;

 

 

 

bottom of page