--- a +++ b/code/preprocessing/EEG/fastica/whitenv.m @@ -0,0 +1,82 @@ +function [newVectors, whiteningMatrix, dewhiteningMatrix] = whitenv ... + (vectors, E, D, s_verbose); +%WHITENV - Whitenv vectors. +% +% [newVectors, whiteningMatrix, dewhiteningMatrix] = ... +% whitenv(vectors, E, D, verbose); +% +% Whitens the data (row vectors) and reduces dimension. Returns +% the whitened vectors (row vectors), whitening and dewhitening matrices. +% +% ARGUMENTS +% +% vectors Data in row vectors. +% E Eigenvector matrix from function 'pcamat' +% D Diagonal eigenvalue matrix from function 'pcamat' +% verbose Optional. Default is 'on' +% +% EXAMPLE +% [E, D] = pcamat(vectors); +% [nv, wm, dwm] = whitenv(vectors, E, D); +% +% +% This function is needed by FASTICA and FASTICAG +% +% See also PCAMAT + +% @(#)$Id$ + +% ======================================================== +% Default value for 'verbose' +if nargin < 4, s_verbose = 'on'; end + +% Check the optional parameter verbose; +switch lower(s_verbose) + case 'on' + b_verbose = 1; + case 'off' + b_verbose = 0; + otherwise + error(sprintf('Illegal value [ %s ] for parameter: ''verbose''\n', s_verbose)); +end + +% ======================================================== +% In some cases, rounding errors in Matlab cause negative +% eigenvalues (elements in the diagonal of D). Since it +% is difficult to know when this happens, it is difficult +% to correct it automatically. Therefore an error is +% signalled and the correction is left to the user. +if any (diag (D) < 0), + error (sprintf (['[ %d ] negative eigenvalues computed from the' ... + ' covariance matrix.\nThese are due to rounding' ... + ' errors in Matlab (the correct eigenvalues are\n' ... + 'probably very small).\nTo correct the situation,' ... + ' please reduce the number of dimensions in the' ... + ' data\nby using the ''lastEig'' argument in' ... + ' function FASTICA, or ''Reduce dim.'' button\nin' ... + ' the graphical user interface.'], ... + sum (diag (D) < 0))); +end + +% ======================================================== +% Calculate the whitening and dewhitening matrices (these handle +% dimensionality simultaneously). +whiteningMatrix = inv (sqrt (D)) * E'; +dewhiteningMatrix = E * sqrt (D); + +% Project to the eigenvectors of the covariance matrix. +% Whiten the samples and reduce dimension simultaneously. +if b_verbose, fprintf ('Whitening...\n'); end +newVectors = whiteningMatrix * vectors; + +% ======================================================== +% Just some security... +if ~isreal(newVectors) + error ('Whitened vectors have imaginary values.'); +end + +% Print some information to user +if b_verbose + fprintf ('Check: covariance differs from identity by [ %g ].\n', ... + max (max (abs (cov (newVectors', 1) - eye (size (newVectors, 1)))))); +end