detect_gaze_shifts_jld.m 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. function [num_shifts, shift_directions] = detect_gaze_shifts(data)
  2. % Input:
  3. % - data: a 2 x N matrix containing the eye movements in the vertical
  4. % and horizontal axes, respectively, over time.
  5. % Output:
  6. % - num_shifts: the total number of gaze shifts detected in the data.
  7. % - shift_directions: a 1 x num_shifts vector containing the direction of
  8. % each gaze shift, where 1 indicates a rightward shift,
  9. % -1 indicates a leftward shift, 2 indicates an upward
  10. % shift, and -2 indicates a downward shift.
  11. % NaN indicates that no direction was detected.
  12. % Set parameters
  13. sampling_rate = 500; % in Hz
  14. vel_threshold = 5 * median(sqrt(sum(diff(data,1,2).^2,1)))/ sampling_rate;
  15. min_saccade_interval = 100 / 1000 * sampling_rate; % in samples
  16. smooth_window_size = 7 / 1000 * sampling_rate; % in samples
  17. % Euclidean distance between succesives time points
  18. edP=sqrt(sum(diff(data,1,2).^2,1));
  19. edP=edP/sampling_rate;
  20. % Smooth the data
  21. data_smooth = smoothdata(edP', 'gaussian', smooth_window_size)'; %Euclidean D smooth
  22. ori_data_smooth = smoothdata(data', 'gaussian', smooth_window_size)'; %Original data smooth
  23. % data_vel = diff(data_smooth, 1, 2);
  24. data_vel = data_smooth;
  25. % Find saccade onsets
  26. % vel_norm = sqrt(sum(data_vel.^2, 1));
  27. saccade_onsets = find(data_vel > vel_threshold);
  28. if isempty(saccade_onsets)
  29. num_shifts = 0;
  30. shift_directions = [];
  31. return;
  32. end
  33. % Remove saccades that are too close in time
  34. saccade_diff = diff(saccade_onsets);
  35. toremove=find(saccade_diff < min_saccade_interval)+1; %index to remove
  36. saccade_onsets(toremove)=[];
  37. % Determine the direction of each gaze shift
  38. num_shifts = length(saccade_onsets);
  39. shift_directions = nan(1, num_shifts);
  40. for i = 1:num_shifts
  41. saccade_start = saccade_onsets(i);
  42. if i < num_shifts
  43. saccade_end = saccade_onsets(i+1) - 1;
  44. else
  45. saccade_end = saccade_onsets(i)+1;
  46. end
  47. posOnset=ori_data_smooth(:,saccade_onsets);
  48. posOffset=ori_data_smooth(:,saccade_end);
  49. dx = posOffset(1) - posOnset(1);
  50. dy = posOffset(2) - posOnset(2);
  51. angle = atan2(dy, dx); %Calculating the distance in radians
  52. shift_directions(i) = angle;
  53. end
  54. end