detectMS_EK03_jld.m 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. function [angles, sizes]=detectMS_EK03(actgaze, smoothing)
  2. % BS and JLD adapted from FieldTrip function ft_detect_movement.m to work without FT
  3. % Inputs: actgaze: the x/y gaze time series of the current trial (2 x nsamples)
  4. % Outputs: vectors of angles (directions) and sizes, respectively, of detected microsaccades.
  5. % Can be modified to output other things like velocity or time of the MS
  6. %% Settings (Engbert & Kliegl 2003)
  7. kernel = [1 1 0 -1 -1].*(500/6); % 500 is Sampling Rate
  8. velthres=8;%6;
  9. mindur=12;%3;
  10. % If Smoothing
  11. if smoothing
  12. sampling_rate=500;
  13. smooth_window_size = 7 / 1000 * sampling_rate; % in samples
  14. actgaze = smoothdata(actgaze', 'gaussian', smooth_window_size)'; %Original data smooth
  15. end
  16. % mean-center the trial
  17. actgaze(1,:)=actgaze(1,:)-nanmean(actgaze(1,:));
  18. actgaze(2,:)=actgaze(2,:)-nanmean(actgaze(2,:));
  19. % padding, to prevent edge effects usign conv
  20. pad=mindur;
  21. padleft=repmat(nanmean(actgaze(:,1:pad),2),1,pad);
  22. padright=repmat(nanmean(actgaze(:,end-pad+1:end),2),1,pad);
  23. padgaze=[padleft actgaze padright];
  24. % velocity time series
  25. vel=convn(padgaze, kernel, 'same');
  26. vel=vel(:,1+pad:end-pad); % remove pad
  27. % velocity exceedance (saccades)
  28. medianstd = sqrt( median(vel.^2,2) - (median(vel,2)).^2 );
  29. radius = velthres*medianstd;
  30. test = sum((vel./radius(:,ones(1,length(actgaze)))).^2,1);
  31. sacsmp = find(test>1); % microsaccade's indexing
  32. %% determine microsaccades per trial
  33. % first find eye movements of n-consecutive time points
  34. j = find(diff(sacsmp)==1);
  35. j1 = [j; j+1];
  36. com = intersect(j,j+1);
  37. cut = ~ismember(j1,com);
  38. sacidx = reshape(j1(cut),2,[]);
  39. sizes=[];
  40. angles=[];
  41. for k=1:size(sacidx,2)
  42. duration = sacidx(1,k):sacidx(2,k);
  43. if size(duration,2) >= mindur
  44. begtrl = sacsmp(duration(1,1)); % begin of MS
  45. endtrl = sacsmp(duration(1,end)); % end of MS
  46. [peakvel, smptrl] = max(sqrt(sum(vel(:,begtrl:endtrl).^2,1)));
  47. veltrl = sacsmp(duration(1,smptrl)); % peak velocity microsaccade sample -> important for spike conversion
  48. % what follows is only some ugly code by BS to average a few (here 3)
  49. % samples before and after the MS, hoping it makes things less noisy
  50. afew=3-1;
  51. if begtrl>afew & endtrl<length(actgaze)-afew
  52. s1=nanmean(actgaze(:,begtrl-afew:begtrl),2); %pre-MS position
  53. s2=nanmean(actgaze(:,endtrl:endtrl+afew),2); %post-MS position
  54. % collect saccade size
  55. sizes=[sizes; pdist([s1'; s2'],'euclidean')];
  56. % calculate saccade direction
  57. sc=s2-s1;
  58. angles=[angles; atan2d(sc(2),sc(1))];
  59. end
  60. end
  61. end
  62. end