function pca2d( x, y, pm, w, h ) % computes covariance matrix from the pairs x, y % diagonalizes covariance matrix, i.e. performs a PCA on [ x, y ] % x and y are column vectors % pm: 0 - scatter of data, 1 - histogram, 2 - multivariate gauss from % covariance matrix, 1 and 2 require w and h % w and h are the width and the height (in data units) for plotting % histograms instead of scatter % covariance matrix: cv = cov( [ x y ] ); % eigen values: [ v , d] = eig( cv ) s = sign( v ); s(1,:) = s(2,:); v = v .* s; % plots: subplot( 2, 2, 1 ); hold on; if (pm > 0) & (nargin == 5) if pm == 1 % histogram of data: xp = -w:0.5:w; yp = -h:0.5:h; [n,c] = hist3([x y], { xp, yp } ); contourf( c{1}, c{2}, n' ); else % bivariate Gaussian: xp = -w:0.1:w; yp = -h:0.1:h; [xg,yg] = meshgrid( xp, yp ); xy = [ xg(:) yg(:) ]; gauss = reshape( exp(-0.5*diag(xy*inv(cv)*xy'))/sqrt((2.0*pi)^2.0*det(cv)), size( xg ) ); contourf( xp, yp, gauss ) end colormap( 'gray' ); else % scatter plot: scatter( x, y, 'b', 'filled', 'MarkerEdgeColor', 'white' ); end % plot eigenvectors: quiver( ones( 1, 2 ).*mean( x ), ones( 1, 2 )*mean(y), v(1,:).*sqrt(diag(d))', v(2,:).*sqrt(diag(d))', 'r', 'LineWidth', 3, 'AutoScale', 'off', 'AutoScaleFactor', 1.0, 'MaxHeadSize', 0.7 ) xlabel( 'x' ); ylabel( 'y' ); axis( 'equal' ); hold off; % histogram of x values: subplot( 2, 2, 3 ); hist( x, 50, 'b' ); xlabel( 'x' ); ylabel( 'count' ); % sort the eigenvalues: [d,inx] = sort( diag(d), 'descend' ); subplot( 2, 2, 2 ); hold on; % subtract means: x = x - mean( x ); y = y - mean( y ); % project onto eigenvectors: nc = [ x y ] * v(:,inx); cv = cov( nc ) [ v , d] = eig( cv ) if (pm > 0) & (nargin == 5) if pm == 1 % histogram of data: [n,c] = hist3( nc, { xp, yp } ); contourf( c{1}, c{2}, n' ); else % bivariate Gaussian: gauss = reshape( exp(-0.5*diag(xy*inv(cv)*xy'))/sqrt((2.0*pi)^2.0*det(cv)), size( xg ) ); contourf( xp, yp, gauss ) end else % scatter plot: scatter( nc(:,1), nc(:,2), 'b', 'filled', 'MarkerEdgeColor', 'white' ); end xlabel( 'n_x' ); ylabel( 'n_y' ); axis( 'equal' ); hold off; % histogram of new x values: subplot( 2, 2, 4 ); hist( nc(:,1), 50, 'b' ); xlabel( 'n_x' ); ylabel( 'count' ); end