Skip to content

Commit

Permalink
fixes for updateVariable 'invert' mode
Browse files Browse the repository at this point in the history
  • Loading branch information
iandol committed May 24, 2023
1 parent fd1d8c7 commit 8812da4
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 41 deletions.
Binary file modified CoreProtocols/Saccade_AntiSaccade.mat
Binary file not shown.
42 changes: 22 additions & 20 deletions CoreProtocols/Saccade_AntiSaccadeStateInfo.m
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
tS.useTask = true; %==use taskSequence (randomises stimulus variables)
tS.rewardTime = 250; %==TTL time in milliseconds
tS.rewardPin = 2; %==Output pin, 2 by default with Arduino.
tS.keyExclusionPattern = ["fixate","fixstim","stimulus"]; %==which states to skip keyboard checking
tS.keyExclusionPattern = ["fixstim","stimulus"]; %==which states to skip keyboard checking
tS.recordEyePosition = false; %==record local copy of eye position, **in addition** to the eyetracker?
tS.askForComments = false; %==UI requestor asks for comments before/after run
tS.saveData = true; %==save behavioural and eye movement data?
Expand Down Expand Up @@ -117,21 +117,19 @@
tS.firstFixRadius = 2;
% do we forbid eye to enter-exit-reenter fixation window?
tS.strict = true;
% do we add an exclusion zone where subject cannot saccade to...
tS.exclusionZone = [];
% time to show both fix and stim
% time to show BOTH fixation cross and [anti]saccade target
tS.fixAndStimTime = 0;
% in this task the subject must saccade to the pro-saccade target location.
% These settings define the rules to "accept" the target fixation as
% correct
tS.targetFixInit = 3; % time to find the target
tS.targetFixTime = 1; % to to maintain fixation on target
tS.targetRadius = 5; %radius to fix within.
tS.targetFixTime = 0.5; % to to maintain fixation on target
tS.targetRadius = [5 10]; %radius to fix within.
% this task will establish an exclusion zone against the anti-saccade
% target for the pro and anti-saccade task. We can change the size of the
% exclusion zone, here set to 5° around the X and Y position of the
% anti-saccade target.
tS.exclusionRadius = 5;
tS.exclusionRadius = [5 10];
% Initialise the eyeTracker object with X, Y, FixInitTime, FixTime, Radius, StrictFix
updateFixationValues(eT, tS.fixX, tS.fixY, tS.firstFixInit, tS.firstFixTime, tS.firstFixRadius, tS.strict);

Expand Down Expand Up @@ -248,7 +246,7 @@
% otherwise 'incorrect' is returned and the state machine will jump there.
% If neither condition matches, then the state table below
% defines that after 5 seconds we will switch to the incorrect state.
@()testSearchHoldFixation(eT,'fixstim','incorrect')
@()testSearchHoldFixation(eT,'fixstim','breakfix')
};

%--------------------exit fixation phase
Expand Down Expand Up @@ -314,7 +312,7 @@

% test we are finding the new target (stimulus 1, the saccade target)
targetFixFn = {
@()testSearchHoldFixation(eT,'correct','breakfix'); % tests finding and maintaining fixation
@()testSearchHoldFixation(eT,'correct','incorrect'); % tests finding and maintaining fixation
};

%as we exit stim presentation state
Expand All @@ -327,7 +325,6 @@

%if the subject is correct (small reward)
correctEntryFn = {
@()timedTTL(rM, tS.rewardPin, tS.rewardTime); % send a reward TTL
@()trackerMessage(eT,'END_RT'); %send END_RT message to tracker
@()trackerMessage(eT,sprintf('TRIAL_RESULT %i',tS.CORRECT)); %send TRIAL_RESULT message to tracker
@()trackerDrawStatus(eT,'Correct! :-)', stims.stimulusPositions);
Expand All @@ -336,7 +333,6 @@
@()setOffline(eT); % set eyelink offline [tobii ignores this]
@()needEyeSample(me,false); % no need to collect eye data until we start the next trial
@()hide(stims); % hide all stims
@()beep(aM, 2000, 0.1, 0.1); % correct beep
@()logRun(me,'CORRECT'); % print current trial info
};

Expand All @@ -347,6 +343,8 @@

%when we exit the correct state
correctExitFn = {
@()beep(aM, tS.correctSound); % correct beep
@()giveReward(rM); % send a reward TTL
@()updatePlot(bR, me); %update our behavioural plot, must come before updateTask() / updateVariables()
@()updateTask(me,tS.CORRECT); %make sure our taskSequence is moved to the next trial
@()updateVariables(me); %randomise our stimuli, and set strobe value too
Expand All @@ -367,7 +365,6 @@
@()setOffline(eT); % set eyelink offline [tobii ignores this]
@()needEyeSample(me,false); % no need to collect eye data until we start the next trial
@()hide(stims); % hide all stims
@()beep(aM,400,0.5,1);
@()logRun(me,'INCORRECT'); %fprintf current trial info
};

Expand All @@ -378,6 +375,7 @@

%incorrect / break exit
incExitFn = {
@()beep(aM,tS.errorSound);
@()updatePlot(bR, me); %update our behavioural plot, must come before updateTask() / updateVariables()
@()updateVariables(me); %randomise our stimuli, set strobe value too
@()update(stims); %update our stimuli ready for display
Expand All @@ -401,7 +399,7 @@
@()setOffline(eT); % set eyelink offline [tobii/irec ignores this]
@()needEyeSample(me,false); % no need to collect eye data until we start the next trial
@()hide(stims); % hide all stims
@()beep(aM, 400, 0.5, 1);
@()beep(aM,tS.errorSound);
@()logRun(me,'BREAKFIX'); %fprintf current trial info
};

Expand Down Expand Up @@ -453,6 +451,10 @@
%--------------------show 1deg size grid
gridFn = { @()drawGrid(s) };

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

%==========================================================================
%==========================================================================
%==========================================================================
Expand All @@ -464,13 +466,13 @@
'pause' 'prefix' inf pauseEntryFn {} {} pauseExitFn;
%---------------------------------------------------------------------------------------------
'prefix' 'fixate' 0.5 pfEntryFn pfWithinFn {} pfExitFn;
'fixate' 'incorrect' 5 fixEntryFn fixWithinFn initFixFn fixExitFn;
'fixstim' 'incorrect' 5 fsEntryFn fsWithinFn fsFixFn fsExitFn
'stimulus' 'incorrect' 5 stimEntryFn stimWithinFn targetFixFn stimExitFn;
'correct' 'prefix' 0.25 correctEntryFn correctWithinFn {} correctExitFn;
'incorrect' 'timeout' 0.25 incEntryFn incWithinFn {} incExitFn;
'breakfix' 'timeout' 0.25 breakEntryFn incWithinFn {} incExitFn;
'exclusion' 'timeout' 0.25 exclEntryFn incWithinFn {} incExitFn;
'fixate' 'breakfix' 10 fixEntryFn fixWithinFn initFixFn fixExitFn;
'fixstim' 'breakfix' 10 fsEntryFn fsWithinFn fsFixFn fsExitFn
'stimulus' 'incorrect' 10 stimEntryFn stimWithinFn targetFixFn stimExitFn;
'correct' 'prefix' 0.1 correctEntryFn correctWithinFn {} correctExitFn;
'breakfix' 'timeout' 0.1 breakEntryFn incWithinFn {} incExitFn;
'incorrect' 'timeout' 0.1 incEntryFn incWithinFn {} incExitFn;
'exclusion' 'timeout' 0.1 exclEntryFn incWithinFn {} incExitFn;
'timeout' 'prefix' tS.tOut {} {} {} {};
%---------------------------------------------------------------------------------------------
'calibrate' 'pause' 0.5 calibrateFn {} {} {};
Expand Down
2 changes: 1 addition & 1 deletion DefaultStateInfo.m
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@

%as we exit stim presentation state
stimExitFcn = {
@()prepareStrobe(io, 255); % 255 indicates stimulus OFF
@()setStrobeValue(me, 255); % 255 indicates stimulus OFF
@()doStrobe(me, true);
};

Expand Down
17 changes: 11 additions & 6 deletions eyetracker/eyetrackerCore.m
Original file line number Diff line number Diff line change
Expand Up @@ -458,18 +458,23 @@ function updateFixationValues(me,x,y,inittime,fixtime,radius,strict)
end

% ===================================================================
%> @brief Sinlge method to update the exclusion zones
%> @brief Sinlge method to update the exclusion zones, can pass multiple
%> x & y values for multiple exclusion zones, sharing the same radius
%>
%> @param x x position in degrees
%> @param y y position in degrees
%> @param radius the radius of the exclusion zone
%> @param x x position[s] in degrees
%> @param y y position[s] in degrees
%> @param radius the radius of the exclusion zone, if length=2 becomes WxH
% ===================================================================
function updateExclusionZones(me,x,y,radius)
resetExclusionZones(me);
if exist('x','var') && exist('y','var') && ~isempty(x) && ~isempty(y)
if ~exist('radius','var'); radius = 5; end
for i = 1:length(x)
me.exclusionZone(i,:) = [x(i)-radius x(i)+radius y(i)-radius y(i)+radius];
if length(radius) == 2
me.exclusionZone(i,:) = [x(i)-radius(1) x(i)+radius(1) y(i)-radius(2) y(i)+radius(2)];
else
me.exclusionZone(i,:) = [x(i)-radius x(i)+radius y(i)-radius y(i)+radius];
end
end
end
end
Expand Down Expand Up @@ -861,7 +866,7 @@ function trackerDrawExclusion(me)
for i = 1:size(me.exclusionZone,1)
drawRect(me.operatorScreen, [me.exclusionZone(1), ...
me.exclusionZone(3), me.exclusionZone(2), ...
me.exclusionZone(4)],[0.7 0.6 0.6 0.7]);
me.exclusionZone(4)],[0.7 0.6 0.6 0.5]);
end
end

Expand Down
24 changes: 10 additions & 14 deletions runExperiment.m
Original file line number Diff line number Diff line change
Expand Up @@ -622,8 +622,7 @@ function runTask(me)
%> method manages the display loop.
%>
% ===================================================================
[rM, aM] = initialiseGlobals(me,true,true);


if exist(me.stateInfoFile,'file') && contains(me.stateInfoFile, 'DefaultStateInfo') && me.stimuli.n == 0
warning('You are trying to start a Default behavioural task without stimuli!');
return
Expand Down Expand Up @@ -653,10 +652,9 @@ function runTask(me)
me.stateInfo = {};
if isa(me.stateMachine,'stateMachine'); me.stateMachine.reset; me.stateMachine = []; end


%------initialise the rewardManager global object
if ~isa(rM,'arduinoManager')
rM=arduinoManager();
end
[rM, aM] = initialiseGlobals(me);
if rM.isOpen
try rM.close; rM.reset; end
end
Expand All @@ -666,16 +664,14 @@ function runTask(me)
end

%------initialise an audioManager for beeps,playing sounds etc.
if ~exist('aM','var') || isempty(aM) || ~isa(aM,'audioManager')
aM=audioManager;
end
aM.device = me.audioDevice;
if isempty(me.audioDevice) || me.audioDevice >= 0
aM.silentMode = false;
reset(aM);
if ~aM.isSetup; try setup(aM); end; end
aM.beep(2000,0.1,0.1);
else
reset(aM);
aM.silentMode = true;
end

Expand Down Expand Up @@ -1746,7 +1742,7 @@ function updateVariables(me, index, override, update)
% what is the index of this variable?
thisVarIndex = me.task.outMap(index, i);
thisVarMax = max(me.task.outMap(:, i));
if isnan(num) || isempty(num)
if any(isnan(num)) || isempty(num)
newIdx = thisVarIndex + 1;
if newIdx > thisVarMax; newIdx = 1; end
else
Expand All @@ -1758,13 +1754,13 @@ function updateVariables(me, index, override, update)
f = find(me.task.outMap(:, i)==newIdx);
val = me.task.outValues{f(1), i};
case {'invert'}
if isnan(num) || isempty(num)
if any(isnan(num)) || isempty(num)
val = -value;
else
val(num) = -value(num);
end
case {'yvar'}
if doXY && ~isnan(num) && ~isempty(num) && length(value)==2
if doXY && ~any(isnan(num)) && ~isempty(num) && length(value)==2
if length(num)==1; var = 0.5; else; var = num(2); end
if rand < var
val = [value(1) value(2)-num(1)];
Expand All @@ -1773,7 +1769,7 @@ function updateVariables(me, index, override, update)
end
end
case {'xvar'}
if doXY && ~isnan(num) && ~isempty(num) && length(value)==2
if doXY && ~any(isnan(num)) && ~isempty(num) && length(value)==2
if length(num)==1; var = 0.5; else; var = num(2); end
if rand < var
val = [value(1)-num(1) value(2)];
Expand All @@ -1782,11 +1778,11 @@ function updateVariables(me, index, override, update)
end
end
case {'yoffset'}
if doXY && ~isnan(num) && ~isempty(num) && length(value)==2
if doXY && ~any(isnan(num)) && ~isempty(num) && length(value)==2
val = [value(1) value(2)+num];
end
case {'xoffset'}
if doXY && ~isnan(num) && ~isempty(num) && length(value)==2
if doXY && ~any(isnan(num)) && ~isempty(num) && length(value)==2
val = [value(1)+num value(2)];
end
otherwise
Expand Down

0 comments on commit 8812da4

Please sign in to comment.