Home > NoiseTools > nt_sns.m

# nt_sns

## PURPOSE

y=nt_sns(x,nneigbors,skip,w) - sensor noise suppression

## SYNOPSIS

function y=nt_sns(x,nneighbors,skip,w)

## DESCRIPTION

     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

## CROSS-REFERENCE INFORMATION

This function calls:

- nt_cov [c,tw]=nt_cov(x,shifts,w) - time shift covariance
- nt_demean [y,mn]=nt_demean(x,w) - remove weighted mean over cols
- nt_fold y=fold(x,epochsize) - fold 2D to 3D
- nt_greetings nt_greetings - display message the first time the toolbox is used
- nt_sns y=nt_sns(x,nneigbors,skip,w) - sensor noise suppression
- nt_sns0 r=nt_sns0(c,nneigbors,skip,wc) - sensor noise suppression
- nt_unfold y=nt_fold(x) - unfold 3D to 2D
- nt_vecmult y=nt_vecmult(x,v) - multiply all rows or columns of matrix by vector

This function is called by:

- nt_find_bad_channels [iBad,toGood]=nt_find_bad_channels(x,proportion,thresh1,thresh2,thresh3) - find bad channels
- nt_sns y=nt_sns(x,nneigbors,skip,w) - sensor noise suppression
- nt_sns1 y=nt_sns1(x,nneigbors,skip,w,threshold) - sensor noise suppression
- nt_sns_cluster y=nt_sns_cluster(x,nneigbors,cluster_size) - sensor noise suppression within clusters

## SOURCE CODE

    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;