function brain_sensor_pod ( ) %*****************************************************************************80 % %% BRAIN_SENSOR_POD treats each set of 40 brain sensor readings as data. % % Discussion: % % We have a 40 x 1500 x 36 array of data, representing readings from % 40 sensors, for 1500 time steps, for 36 individuals. % % The sensors are placed at known locations on the head. We % simplify this information by idealizing the sensors as points % on a sphere of unit radius. % % We now consider each set of 40 sensor readings to be an item % of data, and we apply POD to this data, seeking the first few % dominant or representative modes. We choose these modes to % have unit norm, to be orthogonal, and to be ordered (either % in ascending or descending order). The "most important" modes % are those which have the largest projection onto the given data. % % The sensors are geometrically related. If we make a simplified % flattened map of the sensor locations, that preserves neighbors % and roughly preserves areas and lengths, it is possible to % define a finite element mass matrix for the 2D data, and use % this to try to include some spatial weighting in the POD % calculation. % % This program carries out both the unweighted and weighted versions % of the POD algorithm on the brain sensor data. It displays % the 3 most prominent modes in the data. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 08 May 2010 % % Author: % % Jeff Borggaard % John Burkardt % fprintf ( 1, '\n' ); fprintf ( 1, 'BRAIN_SENSOR_POD\n' ); fprintf ( 1, ' Given a 40x1500x36 array of data,\n' ); fprintf ( 1, ' representing 40 sensor readings, 1500 time steps,\n' ); fprintf ( 1, ' 36 individuals, seek a basis for the sensor data\n' ); fprintf ( 1, ' that reveals the most common sensor data configurations.\n' ); % % Load the data. % load brain_data.mat % % We expect "EEG.data" to be a 40 x 1500 x 36 array. % [ n1, n2, n3 ] = size ( EEG.data ); % % Reshape the data to a 2D array, with each column a sample set of % 40 sensor readings. % DD = reshape ( EEG.data, n1, n2 * n3 ); % % Read the 3D sensor coordinates, compute a set of 2D flattened % coordinates, and a triangulation of them. % [ x, x2d, tri ] = sensor_data ( EEG ); % % Apply POD to the unweighted sensor data. % sensor_pod_unweighted ( n1, DD, x, x2d, tri ); % % Apply POD to the weighted sensor data. % sensor_pod_weighted ( n1, DD, x, x2d, tri ) fprintf ( 1, '\n' ); fprintf ( 1, 'BRAIN_SENSOR_POD\n' ); fprintf ( 1, ' Normal end of execution.\n' ); return end function sensor_pod_unweighted ( npts, DD, x, x2d, tri ) %*****************************************************************************80 % %% SENSOR_POD_UNWEIGHTED does a POD analysis of the unweighted sensor data. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 04 May 2010 % % Author: % % Jeff Borggaard % John Burkardt % % Parameters: % % Input, integer NPTS, the number of sensors. % % Input, real DD(NPTS,1500*36), the data averaged over the realizations. % % Input, real X(NPTS,3), the coordinates of the sensors. % % Input, real X2D(NPTS,2), the coordinates of the sensors in a 2D system. % % Input, integer TRI(3,*), the Delaunay triangulation of the X2D data. % plotting = 1; % % Apply the standard POD or PCA procedure to the data. % A = DD * DD'; [ U, D ] = eig ( A ); S = sqrt ( abs ( diag ( D ) ) ); pmode = 40; qmode = 39; rmode = 38; smode = 37; tmode = 36; xmode = 30; ymode = 20; zmode = 10; U1 = r8col_max_one ( npts, npts, U ); fprintf ( 1, '\n' ); fprintf ( 1, ' S( 1) = %f\n', S(pmode) ); fprintf ( 1, ' S( 2) = %f\n', S(qmode) ); fprintf ( 1, ' S( 3) = %f\n', S(rmode) ); fprintf ( 1, ' S( 4) = %f\n', S(smode) ); fprintf ( 1, ' S( 5) = %f\n', S(tmode) ); fprintf ( 1, ' S(10) = %f\n', S(xmode) ); fprintf ( 1, ' S(20) = %f\n', S(ymode) ); fprintf ( 1, ' S(30) = %f\n', S(zmode) ); if ( plotting ) figure ( 4 ); semilogy ( S ) xlabel ( '-- Mode index --' ); ylabel ( '-- Mode Value --' ); title ( 'Figure 4: Singular values' ); else fprintf ( 1, ' Figure 4, Singular values, skipped.\n' ); end % % Plot dominant modes. % if ( plotting ) figure ( 5 ) trisurf ( tri, x(:,1), x(:,2), x(:,3), U1(:,pmode), 'FaceColor', 'Interp' ) axis equal xlabel ( '-- X --' ); ylabel ( '-- Y --' ); zlabel ( '-- Z --' ); title ( 'Figure 5: Triangulated sensors, first mode' ) else fprintf ( 1, ' Figure 5, Triangulated sensors, first mode, skipped.\n' ); end if ( plotting ) figure ( 55 ) trisurf ( tri, x2d(:,1), x2d(:,2), U1(:,pmode), 'FaceColor', 'Interp' ) view ( 0, 90 ) axis equal xlabel ( '-- X --' ); ylabel ( '-- Y --' ); zlabel ( '-- Z --' ); title ( 'Figure 55: Triangulated sensors, first mode' ) else fprintf ( 1, ' Figure 55, Triangulated sensors, first mode, skipped.\n' ); end if ( plotting ) figure ( 6 ) trisurf ( tri, x(:,1), x(:,2), x(:,3), U1(:,qmode), 'FaceColor', 'Interp' ) axis equal xlabel ( '-- X --' ); ylabel ( '-- Y --' ); zlabel ( '-- Z --' ); title ( 'Figure 6: Triangulated sensors, second mode' ) else fprintf ( 1, ' Figure 6, Triangulated sensors, second mode, skipped.\n' ); end if ( plotting ) figure ( 56 ) trisurf ( tri, x2d(:,1), x2d(:,2), U1(:,qmode), 'FaceColor', 'Interp' ) view ( 0, 90 ) axis equal xlabel ( '-- X --' ); ylabel ( '-- Y --' ); zlabel ( '-- Z --' ); title ( 'Figure 56: Triangulated sensors, second mode' ) else fprintf ( 1, ' Figure 56, Triangulated sensors, second mode, skipped.\n' ); end if ( plotting ) figure ( 7 ) trisurf ( tri, x(:,1), x(:,2), x(:,3), U1(:,rmode), 'FaceColor', 'Interp' ) axis equal xlabel ( '-- X --' ); ylabel ( '-- Y --' ); zlabel ( '-- Z --' ); title ( 'Figure 7: Triangulated sensors, third mode' ) else fprintf ( 1, ' Figure 7, Triangulated sensors, third mode, skipped.\n' ); end if ( plotting ) figure ( 57 ) trisurf ( tri, x2d(:,1), x2d(:,2), U1(:,rmode), 'FaceColor', 'Interp' ) view ( 0, 90 ) axis equal xlabel ( '-- X --' ); ylabel ( '-- Y --' ); zlabel ( '-- Z --' ); title ( 'Figure 57: Triangulated sensors, third mode' ) else fprintf ( 1, ' Figure 57, Triangulated sensors, third mode, skipped.\n' ); end if ( plotting ) figure ( 8 ); plot ( U(:,pmode)' * DD, 'r' ) hold on plot ( U(:,xmode)' * DD, 'g' ) hold on plot ( U(:,ymode)' * DD, 'b' ) hold on plot ( U(:,zmode)' * DD, 'k' ) hold off title('Figure 8: U''DD, RGBK, modes 1, 10, 20, 30') else fprintf ( 1, ' Figure 8, V''DD Standard PCA, skipped.\n' ); end % % Scale so maximum entry is always 1. % if ( plotting ) figure ( 9 ) plot ( U1(:,pmode), 'r', 'LineWidth', 2 ) hold on plot ( U1(:,qmode), 'g', 'LineWidth', 2 ) hold on plot ( U1(:,rmode), 'b', 'LineWidth', 2 ) hold on plot ( U1(:,smode), 'c', 'LineWidth', 2 ) hold on plot ( U1(:,tmode), 'k', 'LineWidth', 2 ) title ('Figure 9: R,G,B,C,K = first 5 modes') hold off else fprintf ( 1, ' Figure 9, First 5 modes, skipped.\n' ); end return end function sensor_pod_weighted ( npts, DD, x, x2d, tri ) %*****************************************************************************80 % %% SENSOR_POD_WEIGHTED does a POD analysis of the weighted sensor data. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 04 May 2010 % % Author: % % Jeff Borggaard % John Burkardt % % Parameters: % % Input, integer NPTS, the number of sensors. % % Input, real DD(NPTS,1500*36), the data averaged over the realizations. % % Input, real X(NPTS,3), the coordinates of the sensors. % % Input, real X2D(NPTS,2), the coordinates of the sensors in a 2D system. % % Input, integer TRI(3,*), the Delaunay triangulation of the X2D data. % plotting = 1; % % Here, the spatial weighting is done on the artificially flattened coordinates. % M = build_mass_2d ( x2d, tri ); M = full ( M ); R = chol ( M ); SN = R * DD; Rwx = SN * SN'; [ U, D ] = eig ( Rwx ); S = sqrt ( abs ( diag ( D ) ) ); U1 = r8col_max_one ( npts, npts, U ); pmode = 40; qmode = 39; rmode = 38; smode = 37; tmode = 36; xmode = 30; ymode = 20; zmode = 10; fprintf ( 1, '\n' ); fprintf ( 1, ' S( 1) = %f\n', S(pmode) ); fprintf ( 1, ' S( 2) = %f\n', S(qmode) ); fprintf ( 1, ' S( 3) = %f\n', S(rmode) ); fprintf ( 1, ' S( 4) = %f\n', S(smode) ); fprintf ( 1, ' S( 5) = %f\n', S(tmode) ); fprintf ( 1, ' S(10) = %f\n', S(xmode) ); fprintf ( 1, ' S(20) = %f\n', S(ymode) ); fprintf ( 1, ' S(30) = %f\n', S(zmode) ); if ( plotting ) figure ( 10 ); semilogy ( S ) xlabel ( '-- Mode index --' ); ylabel ( '-- Mode Value --' ); title ( 'Figure 10: Singular values' ); else fprintf ( 1, ' Figure 10, Singular values, skipped.\n' ); end % % Plot dominant modes. % if ( plotting ) figure ( 11 ) trisurf ( tri, x(:,1), x(:,2), x(:,3), U1(:,pmode), 'FaceColor', 'Interp' ) axis equal xlabel ( '-- X --' ); ylabel ( '-- Y --' ); zlabel ( '-- Z --' ); title ( 'Figure 11: Triangulated sensors, first mode' ) else fprintf ( 1, ' Figure 11, Triangulated sensors, first mode, skipped.\n' ); end if ( plotting ) figure ( 21 ) trisurf ( tri, x2d(:,1), x2d(:,2), U1(:,pmode), 'FaceColor', 'Interp' ) view ( 0, 90 ); axis equal xlabel ( '-- X --' ); ylabel ( '-- Y --' ); zlabel ( '-- Z --' ); title ( 'Figure 21: Triangulated sensors, first mode' ) else fprintf ( 1, ' Figure 21, Triangulated sensors, first mode, skipped.\n' ); end if ( plotting ) figure ( 12 ) trisurf ( tri, x(:,1), x(:,2), x(:,3), U1(:,qmode), 'FaceColor', 'Interp' ) axis equal xlabel ( '-- X --' ); ylabel ( '-- Y --' ); zlabel ( '-- Z --' ); title ( 'Figure 12: Triangulated sensors, second mode' ) else fprintf ( 1, ' Figure 12, Triangulated sensors, second mode, skipped.\n' ); end if ( plotting ) figure ( 22 ) trisurf ( tri, x2d(:,1), x2d(:,2), U1(:,qmode), 'FaceColor', 'Interp' ) view ( 0, 90 ); axis equal xlabel ( '-- X --' ); ylabel ( '-- Y --' ); zlabel ( '-- Z --' ); title ( 'Figure 22: Triangulated sensors, second mode' ) else fprintf ( 1, ' Figure 22, Triangulated sensors, second mode, skipped.\n' ); end if ( plotting ) figure ( 13 ) trisurf ( tri, x(:,1), x(:,2), x(:,3), U1(:,rmode), 'FaceColor', 'Interp' ) axis equal xlabel ( '-- X --' ); ylabel ( '-- Y --' ); zlabel ( '-- Z --' ); title ( 'Figure 13: Triangulated sensors, third mode' ) else fprintf ( 1, ' Figure 13, Triangulated sensors, third mode, skipped.\n' ); end if ( plotting ) figure ( 23 ) trisurf ( tri, x2d(:,1), x2d(:,2), U1(:,rmode), 'FaceColor', 'Interp' ) view ( 0, 90 ) axis equal xlabel ( '-- X --' ); ylabel ( '-- Y --' ); zlabel ( '-- Z --' ); title ( 'Figure 23: Triangulated sensors, third mode' ) else fprintf ( 1, ' Figure 23, Triangulated sensors, third mode, skipped.\n' ); end if ( plotting ) figure ( 15 ); plot ( U(:,pmode)' * DD, 'r' ) hold on plot ( U(:,xmode)' * DD, 'g' ) hold on plot ( U(:,ymode)' * DD, 'b' ) hold on plot ( U(:,zmode)' * DD, 'k' ) hold off title('Figure 15: U''DD, RGBK, weighted modes 1, 10, 20, 30') else fprintf ( 1, ' Figure 15, V''DD Standard PCA, skipped.\n' ); end if ( plotting ) figure ( 14 ) plot ( U1(:,pmode), 'r', 'LineWidth', 2 ) hold on plot ( U1(:,qmode), 'g', 'LineWidth', 2 ) hold on plot ( U1(:,rmode), 'b', 'LineWidth', 2 ) hold on plot ( U1(:,smode), 'c', 'LineWidth', 2 ) hold on plot ( U1(:,tmode), 'k', 'LineWidth', 2 ) title ('Figure 14: R,G,B,C,K = first 5 modes') hold off else fprintf ( 1, ' Figure 14, First 5 modes, skipped.\n' ); end return end function a = r8col_max_one ( m, n, a ) %*****************************************************************************80 % %% R8COL_MAX_ONE scales the columns of an R8COL for a maximum of one. % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 08 May 2010 % % Author: % % John Burkardt % % Parameters: % % Input, integer M, N, the number of rows and columns. % % Input, real A(M,N), the array. % % Output, real A(M,N), the rescaled array. % for j = 1 : m i_big = 1; for i = 2 : n if ( abs ( a(i_big,j) ) < abs ( a(i,j) ) ) i_big = i; end end if ( a(i_big,j) ~= 0.0 ) a(1:m,j) = a(1:m,j) / a(i_big,j); end end return end