Skip to content

Commit 5cd88ec

Browse files
committed
Merge branch 'master' into release
2 parents ef84da8 + 2fa36a2 commit 5cd88ec

File tree

2 files changed

+40
-3
lines changed

2 files changed

+40
-3
lines changed

functions/I2MC/I2MCfunc.m

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
par.maxerrors = 100; % maximum number of errors allowed in k-means clustering procedure before proceeding to next file
3535
% FIXATION DETERMINATION
3636
par.cutoffstd = 2; % number of standard deviations above mean k-means weights will be used as fixation cutoff
37+
par.onoffsetThresh = 3; % number of MAD away from median fixation duration. Will be used to walk forward at fixation starts and backward at fixation ends to refine their placement and stop algorithm from eating into saccades
3738
par.maxMergeDist = 30; % maximum Euclidean distance in pixels between fixations for merging
3839
par.maxMergeTime = 30; % maximum time in ms between fixations for merging
3940
par.minFixDur = 40; % minimum fixation duration (ms) after merging, fixations with shorter duration are removed from output
@@ -51,7 +52,7 @@
5152
end
5253
value = varargin{p+1};
5354
switch key
54-
case {'xres','yres','freq','missingx','missingy','disttoscreen','windowtimeInterp','maxdisp','windowtime','steptime','cutoffstd','maxMergeDist','maxMergeTime','minFixDur'}
55+
case {'xres','yres','freq','missingx','missingy','disttoscreen','windowtimeInterp','maxdisp','windowtime','steptime','cutoffstd','onoffsetThresh','maxMergeDist','maxMergeTime','minFixDur'}
5556
checkNumeric(value,key);
5657
checkScalar(value,key);
5758
par.(key) = value;
@@ -195,6 +196,6 @@
195196

196197
%% DETERMINE FIXATIONS BASED ON FINALWEIGHTS_AVG
197198
fprintf('Determining fixations based on clustering weight mean for averaged signal and separate eyes + 2*std \n')
198-
[fix.cutoff,fix.start,fix.end,fix.startT,fix.endT,fix.dur,fix.xpos,fix.ypos,fix.flankdataloss,fix.fracinterped] = getFixations(data.finalweights,data.time,xpos,ypos,missing,par.cutoffstd,par.maxMergeDist,par.maxMergeTime,par.minFixDur);
199+
[fix.cutoff,fix.start,fix.end,fix.startT,fix.endT,fix.dur,fix.xpos,fix.ypos,fix.flankdataloss,fix.fracinterped] = getFixations(data.finalweights,data.time,xpos,ypos,missing,par.cutoffstd,par.onoffsetThresh,par.maxMergeDist,par.maxMergeTime,par.minFixDur);
199200
[fix.RMSxy,fix.BCEA,fix.fixRangeX,fix.fixRangeY] = getFixStats(xpos,ypos,missing,fix.start,fix.end,pixperdeg);
200201

functions/I2MC/getFixations.m

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
function [cutoff,fixstart,fixend,starttime,endtime,fixdur,xmedian,ymedian,flankdataloss,fracinterped] = getFixations(finalweights,timestamp,xpos,ypos,missing,cutoffstd,maxMergeDist,maxMergeTime,minFixDur)
1+
function [cutoff,fixstart,fixend,starttime,endtime,fixdur,xmedian,ymedian,flankdataloss,fracinterped] = getFixations(finalweights,timestamp,xpos,ypos,missing,cutoffstd,onoffsetThresh,maxMergeDist,maxMergeTime,minFixDur)
22
% determine fixations based on finalweights from 2-means clustering
33

44
% Roy Hessels - 2014
@@ -12,6 +12,8 @@
1212
% missing (originally, before interpolation!)
1313
% cutoffstd = number of std above mean clustering-weight to
1414
% use as fixation cutoff
15+
% onoffsetThresh = threshold (x*MAD of fixation) for walking
16+
% forward/back for saccade off- and onsets
1517
% maxMergeDist = maximum Euclidean distance in pixels between fixations for merging
1618
% maxMergeTime = maximum time in ms between fixations for merging
1719

@@ -43,6 +45,40 @@
4345
% get indices of where fixations start and end
4446
[fixstart,fixend] = bool2bounds(fixbool);
4547

48+
% for each fixation start, walk forward until recorded position is below a
49+
% threshold of lambda*MAD away from median fixation position.
50+
% same for each fixation end, but walk backward
51+
for p=1:length(fixstart)
52+
xmedThis = median(xpos(fixstart(p):fixend(p)));
53+
ymedThis = median(ypos(fixstart(p):fixend(p)));
54+
% MAD = median(abs(x_i-median({x}))). For the 2D version, I'm using
55+
% median 2D distance of a point from the median fixation position. Not
56+
% exactly MAD, but makes more sense to me for 2D than city block,
57+
% especially given that we use 2D distance in our walk here
58+
MAD = median(hypot(xpos(fixstart(p):fixend(p))-xmedThis, ypos(fixstart(p):fixend(p))-ymedThis));
59+
60+
thresh = MAD*onoffsetThresh;
61+
62+
% walk until distance less than threshold away from median fixation
63+
% position. No walking occurs when we're already below threshold.
64+
i = fixstart(p);
65+
if i>1 % don't walk when fixation starting at start of data
66+
while hypot(xpos(i)-xmedThis,ypos(i)-ymedThis)>thresh
67+
i = i+1;
68+
end
69+
fixstart(p) = i;
70+
end
71+
72+
% and now fixation end.
73+
i = fixend(p);
74+
if i<length(xpos) % don't walk when fixation ending at end of data
75+
while hypot(xpos(i)-xmedThis,ypos(i)-ymedThis)>thresh
76+
i = i-1;
77+
end
78+
fixend(p) = i;
79+
end
80+
end
81+
4682
% get start time, end time, and fix duration
4783
starttime = timestamp(fixstart);
4884
endtime = timestamp(fixend);

0 commit comments

Comments
 (0)