DetectSaccades360.m 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. % function DetectSaccades360.m
  2. %
  3. % This function detects saccades from the provided data. It is based on the
  4. % saccade detector described in Dorr, Michael, et al. "Variability of eye
  5. % movements when viewing dynamic natural scenes." Journal of vision 10.10
  6. % (2010): 28-28.
  7. %
  8. % input:
  9. % data - data from the ARFF file
  10. % metadata - metadata from the ARFF file
  11. % attributes - attributes from the ARFF file
  12. % typeOfMotion- 1 -> eye FOV, 2 -> eye+head
  13. % params - parameters to use for saccade detection
  14. %
  15. % output:
  16. % result - logical vector with the same length as data and true where a saccade is detected
  17. %
  18. % params format:
  19. % params is a data structure with the following fields
  20. %
  21. % params.tolerance;
  22. % params.thresholdOnsetFast;
  23. % params.thresholdOnsetSlow;
  24. % params.thresholdOffset;
  25. % params.maxSpeed;
  26. % params.minDuration;
  27. % params.maxDuration;
  28. % params.velIntegrationInterv;
  29. % params.minConfidence
  30. function result = DetectSaccades360(data, metadata, attributes, typeOfMotion, params)
  31. c_tolerance = params.tolerance;
  32. c_thresholdOnsetFast = params.thresholdOnsetFast;
  33. c_thresholdOnsetSlow = params.thresholdOnsetSlow;
  34. c_thresholdOffset = params.thresholdOffset;
  35. c_maxSpeed = params.maxSpeed;
  36. c_minDuration = params.minDuration;
  37. c_maxDuration = params.maxDuration;
  38. c_velIntegrationInterv = params.velIntegrationInterv;
  39. c_minConf = params.minConfidence;
  40. timeInd = GetAttPositionArff(attributes, 'time');
  41. xInd = GetAttPositionArff(attributes, 'x');
  42. yInd = GetAttPositionArff(attributes, 'y');
  43. confInd = GetAttPositionArff(attributes, 'confidence');
  44. % initialize result
  45. result = false(size(data,1),1);
  46. if (size(data,1) < 10)
  47. return;
  48. end
  49. [eyeFovVec, eyeHeadVec, headVec] = GetCartVectors(data, metadata, attributes);
  50. if (typeOfMotion == 1)
  51. vecList = eyeFovVec;
  52. elseif (typeOfMotion == 2)
  53. vecList = eyeHeadVec;
  54. elseif (typeOfMotion == 3)
  55. vecList = headVec;
  56. else
  57. error('Uknown motion');
  58. end
  59. speed = GetSpeed(vecList, data(:,timeInd));
  60. % create glitch array
  61. glitch = zeros(size(data,1),1);
  62. glitch(data(:,xInd) > (1+c_tolerance)*metadata.width_px) = 1;
  63. glitch(data(:,xInd) < -c_tolerance*metadata.width_px) = 1;
  64. glitch(data(:,yInd) > (1+c_tolerance)*metadata.height_px) = 1;
  65. glitch(data(:,yInd) < -c_tolerance*metadata.height_px) = 1;
  66. glitch(data(:,confInd) < c_minConf) = 0.75;
  67. isSaccActive = 0;
  68. onsetSlowIndex = 1;
  69. for i=1:size(data,1)
  70. % not in glitch
  71. if (glitch(i) == 0)
  72. if (isSaccActive == 0)
  73. % if speed less than onset slow move index
  74. if (speed(i) < c_thresholdOnsetSlow)
  75. onsetSlowIndex = i+1;
  76. end
  77. % saccade above fast threshold but below physically impossible
  78. if (speed(i) > c_thresholdOnsetFast && speed(i) < c_maxSpeed)
  79. isSaccActive = 1;
  80. % allocate all samples from onset slow as saccade
  81. result(onsetSlowIndex:i) = 1;
  82. end
  83. end
  84. % if within saccade check for termination cases otherwise make sample part of saccade
  85. if (isSaccActive == 1)
  86. % saccade termination cases
  87. if (speed(i) < c_thresholdOffset)
  88. isSaccActive = 0;
  89. % check for minDuration
  90. if (data(i,timeInd)-data(onsetSlowIndex,timeInd) < c_minDuration)
  91. result(onsetSlowIndex:i-1) = 0;
  92. end
  93. continue; % skip rest of the loop
  94. end
  95. if (data(i,timeInd)-data(onsetSlowIndex,timeInd) > c_maxDuration)
  96. isSaccActive = 0;
  97. continue;
  98. end
  99. % check if onset and current point are the same
  100. if (i-onsetSlowIndex < 1)
  101. continue
  102. end
  103. meanVel = mean(speed(onsetSlowIndex:i-1));
  104. if (meanVel < c_thresholdOnsetSlow)
  105. isSaccActive = 0;
  106. % check for minDuration
  107. if (data(i,timeInd)-data(onsetSlowIndex,timeInd) < c_minDuration)
  108. result(onsetSlowIndex:i-1) = 0;
  109. end
  110. continue;
  111. end
  112. result(i) = 1;
  113. end
  114. else
  115. onsetSlowIndex = i+1;
  116. end
  117. end
  118. end