y=nt_sns(x,nneigbors,skip,w) - sensor noise suppression y: denoised matrix x: matrix to denoise nneighbors: number of channels to use in projection skip: number of closest neighbors to skip (default: 0) w : weights (default: all ones) If w=='auto', the weights are calculated automatically. Mean of data is NOT removed. Cite: de Cheveign\'e, A. and Simon, J. Z. (2007). "Sensor Noise Suppression." Journal of Neuroscience Methods, 168: 195-202. NoiseTools
0001 function y=nt_sns(x,nneighbors,skip,w) 0002 % y=nt_sns(x,nneigbors,skip,w) - sensor noise suppression 0003 % 0004 % y: denoised matrix 0005 % 0006 % x: matrix to denoise 0007 % nneighbors: number of channels to use in projection 0008 % skip: number of closest neighbors to skip (default: 0) 0009 % w : weights (default: all ones) 0010 % 0011 % If w=='auto', the weights are calculated automatically. 0012 % 0013 % Mean of data is NOT removed. 0014 % 0015 % Cite: 0016 % de Cheveign\'e, A. and Simon, J. Z. (2007). "Sensor Noise Suppression." 0017 % Journal of Neuroscience Methods, 168: 195-202. 0018 % 0019 % NoiseTools 0020 nt_greetings; 0021 0022 0023 % Copyright 2007, 2008 Alain de Cheveigne 0024 0025 0026 % 0027 % The basic idea is to project each channel of X on a basis formed by the 0028 % orthogonalized set of other channels. Supposing (a) that sensor noise is 0029 % uncorrelated across sensors, and (b) genuine signal is correlated, sensor 0030 % noise is removed and genuine signal preserved. 0031 % 0032 % Implementation issues: 0033 % - Data are often available as an array of epochs. This implementation 0034 % caters for 3D data (time * channnels * trials); 0035 % - It is important to deemphasize high amplitude artifacts and glitches 0036 % so that they do not dominate the solution. This implementation uses 0037 % weighted covariance and means. 0038 % - Processing assumes zero-means data. Means are calculated with weights. 0039 % - The implementation tries to be efficent and minimize memory requirements 0040 % so as to handle large data sets. 0041 % 0042 % Larger data sets (disk based) could be handled by performing mean and 0043 % covariance calculations block-by-block, in several passes. 0044 0045 0046 if nargin<4; w=[]; end 0047 if nargin<3 || isempty(skip); skip=0; end 0048 if nargin<2 || isempty(nneighbors); error('need to specify nneighbors'); end 0049 if ~isempty(w) && sum(w(:))==0; error('weights are all zero!'); end 0050 0051 if ~isempty(find(isnan(x))); error('x contains NANs'); end 0052 if numel(nneighbors)>1 || numel(skip)>1; error('nneighbors & skip should be scalars'); end 0053 0054 [m,n,o]=size(x); 0055 x=nt_unfold(x); 0056 0057 %[x,mn0]=demean(x); % remove mean 0058 [c,nc]=nt_cov(x); % raw covariance 0059 0060 TOOBIG=10; 0061 if strcmp(w,'auto') 0062 y=nt_sns(nt_demean(x),nneighbors,skip); 0063 d=(y-x).^2; 0064 d=nt_vecmult(nt_unfold(d), 1./mean( [mean(nt_unfold(x.^2)); mean(nt_unfold(y.^2))] )); 0065 w=d<TOOBIG; 0066 w=min(w,[],2); 0067 w(find(isnan(w)))=0; 0068 end 0069 0070 0071 % sns matrix 0072 if ~isempty(w); 0073 w=nt_unfold(w); 0074 %[x,mn1]=demean(x,w); 0075 [wc,nwc]=nt_cov(nt_demean(x,w),[],w); % weighted covariance 0076 r=nt_sns0(c,nneighbors,skip,wc); 0077 else 0078 mn1=0; 0079 w=ones(n,o); 0080 r=nt_sns0(c,nneighbors,skip,c); 0081 end 0082 0083 0084 % apply to data 0085 y=x*r; 0086 0087 y=nt_fold(y,m); 0088 0089 %mn=mn0;%+mn1;