THG_FASTER_3_ICA_artifacts_20140305.m 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. function [index parm zval] = THG_FASTER_3_ICA_artifacts_20140305(cfg,data)
  2. %% defaults
  3. if ~isfield(cfg,'criterion'); criterion = 3; else criterion = cfg.criterion; end
  4. if ~isfield(cfg,'recursive'); recursive = 1; else recursive = strcmp(cfg.recursive,'yes'); end
  5. %% components
  6. comp = ft_componentanalysis(cfg,data);
  7. %% parameter:
  8. %% - spatial kurtosis
  9. parm.ica_kurt = kurtosis(comp.topo)';
  10. zval.ica_kurt = zscore(parm.ica_kurt);
  11. %% - hurst exponent
  12. % calculate hurst exponent
  13. for t = 1:length(comp.trial)
  14. display(['processing trial ' num2str(t)])
  15. for c = 1:length(comp.label)
  16. hurst(c,t) = cm_heuristic_hurst_exponent_20140302(comp.trial{t}(c,:));
  17. end; clear c
  18. end; clear t
  19. % z statistic of average hurst exponent
  20. parm.ica_hurst = mean(hurst,2);
  21. zval.ica_hurst = zscore(parm.ica_hurst);
  22. %% - median gradient
  23. % calculate gradients (trial-wise)
  24. for t = 1:length(comp.trial)
  25. med{t} = diff(comp.trial{t}')';
  26. end; clear t
  27. % median gradient
  28. parm.ica_med = median(cell2mat(med)')';
  29. zval.ica_med = zscore(parm.ica_med);
  30. %% - high-frequency distribution
  31. % demean
  32. cfg_.demean = 'yes';
  33. comp_ = ft_preprocessing(cfg_,comp);
  34. % normalization
  35. tmp = cell2mat(comp_.trial);
  36. SD = std(tmp',1)';
  37. for t = 1:length(comp.trial)
  38. comp_.trial{t} = comp_.trial{t} ./ (SD * ones(1,size(comp_.trial{t},2)));
  39. end; clear t
  40. % prepare fft
  41. fftcfg.method = 'mtmfft';
  42. fftcfg.output = 'pow';
  43. fftcfg.channel = 'all';
  44. fftcfg.foilim = [cfg.fft.lowlim cfg.fft.uplim];
  45. fftcfg.taper = 'hanning';
  46. % fft
  47. fftdat = ft_freqanalysis(fftcfg,comp_);
  48. % zscores by frequenices
  49. zfft = zscore(fftdat.powspctrm);
  50. % mean & subsequent zscore
  51. parm.ica_fft = mean(zfft(:,find(fftdat.freq >= 30 & fftdat.freq <= 100)),2);
  52. zval.ica_fft = zscore(parm.ica_fft);
  53. %% high- to low-freq ratio
  54. ind1 = find(fftdat.freq <= 30);
  55. ind2 = find(fftdat.freq > 30);
  56. fft1 = mean(fftdat.powspctrm(:,ind1),2);
  57. fft2 = mean(fftdat.powspctrm(:,ind2),2);
  58. % mean & subsequent zscore
  59. parm.ica_rat = fft2./fft1;
  60. zval.ica_rat = zscore(parm.ica_rat);
  61. %% find outlier
  62. % temporary zscores
  63. tmpz = zval;
  64. % spatial kurtosis outlier
  65. tmpz.ica_kurt = outlier2nan(tmpz.ica_kurt,criterion,recursive);
  66. % hurst exponent outlier
  67. tmpz.ica_hurst = outlier2nan(tmpz.ica_hurst,criterion,recursive);
  68. % median gradient outlier
  69. tmpz.ica_med = outlier2nan(tmpz.ica_med,criterion,recursive);
  70. % fft outlier
  71. tmpz.ica_fft = outlier2nan(tmpz.ica_fft,criterion,recursive);
  72. % ration outlier
  73. tmpz.ica_rat = outlier2nan(tmpz.ica_rat,criterion,recursive);
  74. %% plot outlier
  75. % figure; imagesc(isnan([tmpz.ica_kurt tmpz.ica_hurst tmpz.ica_med tmpz.ica_fft tmpz.ica_rat]))
  76. %% mark outlier
  77. index = find( isnan(tmpz.ica_kurt) | isnan(tmpz.ica_hurst) | ...
  78. isnan(tmpz.ica_med) | isnan(tmpz.ica_fft) | isnan(tmpz.ica_rat) );
  79. % alternative: fixed values
  80. index2 = find(parm.ica_kurt > 30 | parm.ica_rat > 1 );
  81. % merge
  82. index = unique([index; index2]);
  83. % exclude blink, move, heart components
  84. cnt = 1;
  85. ex = [];
  86. for j = 1:length(cfg.labeled)
  87. ind_ = find(index == cfg.labeled(j));
  88. if ~isempty(ind_)
  89. ex(cnt) = ind_;
  90. cnt = cnt + 1;
  91. end
  92. clear ind_
  93. end; clear j
  94. % keep unique indices
  95. index(ex) = [];
  96. index = sortrows(index);
  97. end
  98. %% subfunction outlier2nan (replace outliers with NaN)
  99. function data = outlier2nan(data,criterion,recursive)
  100. %% find epochs
  101. % make sure data orientation is ok (i.e. N X 1 data points)
  102. sz = size(data);
  103. if sz(1) == 1 && sz(2) > 1
  104. data = data';
  105. elseif sz(2) == 1 && sz(1) > 1
  106. data = data;
  107. end
  108. % temporary z values
  109. z = cm_nanzscore_140302(data);
  110. % initialize index variable
  111. index = [];
  112. % find indices to exclude
  113. index = find( z > criterion );
  114. % replace outliers with NaNs
  115. data(index) = NaN;
  116. z(index) = NaN;
  117. % recursive exclusion
  118. if recursive
  119. if ~isempty(index)
  120. check = 0;
  121. while check == 0
  122. % number of excluded outliers
  123. Nex = length(index);
  124. % new zscore calculation after outlier exclusion
  125. z = cm_nanzscore_140302(z);
  126. % find channels to exclude
  127. index_2 = find( z > criterion );
  128. % update index
  129. index = [index; index_2];
  130. % update data
  131. data(index) = NaN;
  132. z(index) = NaN;
  133. % check if additional channel excluded
  134. if Nex == length(index)
  135. check = 1;
  136. end
  137. % clear variables
  138. clear Nex index_2
  139. end; clear check
  140. end
  141. end
  142. end