1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- % DetectOKN360.m
- %
- % This function detects optokinetic nystagmus for 360 degrees data. It uses a
- % two step process. In the first step it detects points were the direction
- % difference around a point is greater than 90 degrees. In the second step
- % it compares the FOV speed of the intervals. If it is above a threshold then
- % it is considered as OKN
- %
- % NOTE: OKN is calculated only in FOV representation. Also saccades have to be
- % annotated in advance.
- %
- % input:
- % arffFile - file with ARFF data
- % saccAttName - name of the saccade attribute
- % saccValue - integer value representing saccades
- %
- % output:
- % result - a logical vector of the same size as the data in the ARFF with true value
- % when OKN occurs
- function result = DetectOKN360(arffFile, saccAttName, saccValue)
- c_minIntAngle = 90; % minimum angle between saccade and subsequent interval
- c_maxIntSaccAngle = 70; % maximum angle between saccades
- c_minIntSpeed = 10; % degrees/sec
- c_saccAttVal = saccValue;
- c_OKNlabel = 1;
- [data, metadata, attributes] = LoadArff(arffFile);
- timeInd = GetAttPositionArff(attributes, 'time');
- [eyeFovVec, eyeHeadVec, headVec] = GetCartVectors(data, metadata, attributes);
- saccInts = GetIntervalsIndexArff(data, attributes, saccAttName, c_saccAttVal);
- result = zeros(size(data,1),1);
- attInd = GetAttPositionArff(attributes, saccAttName);
- %result(data(:,attInd) == c_saccAttVal) = c_OKNlabel;
- for ind=1:size(saccInts,1)-1
- saccDir1 = eyeFovVec(saccInts(ind,2),:) - eyeFovVec(saccInts(ind,1),:);
- saccDir2 = eyeFovVec(saccInts(ind+1,2),:) - eyeFovVec(saccInts(ind+1,1),:);
- % inter-saccadic direction
- intSaccDir = eyeFovVec(saccInts(ind+1,1)-1,:) - eyeFovVec(saccInts(ind,2)+1,:);
- if (sum(saccDir1) == 0 || sum(saccDir2) == 0 || sum(intSaccDir) == 0)
- continue;
- end
- saccDir1 = saccDir1 / norm(saccDir1);
- saccDir2 = saccDir2 / norm(saccDir2);
- intSaccDir = intSaccDir / norm(intSaccDir);
- relDirSacc = GetDispersion(saccDir1, saccDir2);
- relDirIntSacc1 = GetDispersion(saccDir1, intSaccDir);
- relDirIntSacc2 = GetDispersion(saccDir2, intSaccDir);
- dur = data(saccInts(ind+1,1)-1, timeInd) - data(saccInts(ind,2)+1, timeInd);
- dur = dur / 1000000;
- ampl = GetDispersion(eyeFovVec(saccInts(ind+1,1)-1,:), eyeFovVec(saccInts(ind,2)+1,:));
- speed = ampl / dur;
- if (relDirSacc < c_maxIntSaccAngle && ...
- relDirIntSacc1 > c_minIntAngle && ...
- relDirIntSacc2 > c_minIntAngle && ...
- speed > c_minIntSpeed)
- %if ((relDirIntSacc1 > c_minIntAngle || ...
- % relDirIntSacc2 > c_minIntAngle) && ...
- % speed > c_minIntSpeed)
- result(saccInts(ind,2)+1:saccInts(ind+1,1)-1) = c_OKNlabel;
- end
- end
- % Iterate again through saccade intervals and make sure that at least two
- % OKN intervals exist continuously.
- for ind=2:size(saccInts,1)-1
- if (result(saccInts(ind,2)+1) == c_OKNlabel)
- if (result(saccInts(ind,1) -1) ~= c_OKNlabel && ... % previous interval
- result(saccInts(ind+1,2)+1) ~= c_OKNlabel) % next interval
- result(saccInts(ind,2)+1:saccInts(ind+1,1)-1) = 0;
- end
- end
- % assign OKN label to saccades between OKN intervals
- if (result(saccInts(ind,1) -1) == c_OKNlabel && ...
- result(saccInts(ind,2)+1) == c_OKNlabel)
- result(saccInts(ind,1):saccInts(ind,2)) = c_OKNlabel;
- end
- end
- confInd = GetAttPositionArff(attributes, 'confidence');
- result(data(:,confInd) < 1) = 0;
- result = logical(result);
- end
|