function [S,f,v,e] = peig(varargin) // Psuedospectrum using the eigenvector method. // // Calling Sequence // [S,w] = peig(x,p) // [S,w] = peig(x,p,w) // [S,w] = peig(x,p,nfft) // [S,w] = peig(x,p,nfft,fs) // [S,w] = peig(x,p,f,fs) // [S,f] = peig(...,'corr') // [S,f] = peig(x,p,nfft,fs,nwin,noverlap) // [...] = peig(...,freqrange) // [...,v,e] = peig(...) // // Parameters: // x - int|double - vector|matrix // Input signal. In case of a matrix, each row of x represents a // seperate observation of the signal. If 'corr' flag is specified, // then x is the correlation matrix. // If w is not specified in the input, it is determined by the // algorithm. If x is real valued, then range of w is [0, pi]. // Otherwise, the range of w is [0, 2pi) // p - int|double - scalar|vector // p(1) is the dimension of the signal subspace // p(2), if specified, represents a threshold that is multiplied by // the smallest estimated eigenvalue of the signal's correlation matrix. // w - int|double - vector // w is the vector of normalized frequencies over which the // pseuspectrogram is to be computed. // nfft - int - scalar (Default = 256) // Length of the fft used to compute pseudospectrum. The length of S // (and hence w/f) depends on the type of values in x and nfft. // If x is real, length of s is (nfft/2 + 1) {Range of w = [0, pi]} if // nfft is even and (nfft+1)/2 {Range of w = [0, pi)} otherwise. // If x is complex, length of s is nfft. // fs - int|double - scalar (Default = 1) // Sampling rate. Used to convert the normalized frequencies (w) to // actual values (f) and vice-versa. // nwin - int|double - scalar (int only)|vector (Default = 2*p(1)) // If nwin is scalar, it is the length of the rectangular window. // Otherwise, the vector input is considered as the window coefficients. // Not used if 'corr' flag present. // If x is a vector, windowing not done in nwin in scalar. If x is a // matrix, // noverlap - int - scalar (Default = nwin-1) // number of points by which successive windows overlap. noverlap not // used if x is a matrix // freqrange - string // The range of frequencies over which the pseudospetrogram is // computed. Three possible values - 'onesided', 'twosided', 'centered' // 'corr' flag // Presence indicates that the primary input x is actually a // correlation matrix // // Examples: //1. // fs = 100; // t = 0:1/fs:1-1/fs; // s = 2*sin(2*%pi*25*t)+sin(2*%pi*35*t)+rand(1,100,"normal"); // [S,w]=peig(s,2,512,fs,'half'); // plot(w,S); //OUTPUT: gives the plot of power vs normalised frequencies ////2. // fs = 100; //t = 0:1/fs:1-1/fs; //s = 2*sin(2*%pi*25*t)+sin(2*%pi*35*t); //[S,w]=peig(s,2,512,fs,'half'); //plot(w,S); //EXECUTE FUNCTIONS subspaceMethodsInputPars.sci, musicBase.sci PRIOR THE EXECUTION OF THIS FUNCTION // See also // rooteig | pmusic | pmtm | pcov | pmcov | pburg | pyulear | pwelch | corrmtx // // Authors // Ayush Baid // // References // [1] Petre Stoica and Randolph Moses, Introduction To Spectral // Analysis, Prentice-Hall, 1997, pg. 15 // [2] S. J. Orfanidis, Optimum Signal Processing. An Introduction. // 2nd Ed., Macmillan, 1988. funcprot(0); [data, msg, err_num] = subspaceMethodsInputPars(varargin); if length(msg)==0 then // no error occured else error(err_num, "peig: " + msg); end [musicData,msg] = musicBase(data); if length(msg)~=0 then error("peig: " + msg); end // computing the pseudospectrum [S,f] = pseudospectrum(musicData.noiseEigenvects, ... musicData.eigenvals,data.w,data.nfft, data.fs, data.freqrange,data.isFsSpecified); v = musicData.noiseEigenvects; e = musicData.eigenvals; endfunction function [pspec,w] = pseudospectrum(noiseEigenvects, eigenvals, freqvector, ... nfft, fs, freqrange,isFsSpecified) // disp("noise eigenvects in pseudospectrum - "); // disp(noiseEigenvects); // NOTE: the only difference from the pmusic code // Using the noise subspace eigenvalues as weights weights = eigenvals(($-size(noiseEigenvects,2)+1):$); denominator = 0; isFreqGiven = %F; for i=1:size(noiseEigenvects,2); // disp("looping in pseudospectrum"); if isempty(freqvector) then [h,w] = computeFreqResponseByFFT(noiseEigenvects(:,i),nfft,fs,... isFsSpecified); else [h,w] = computeFreqResponseByPolyEval(noiseEigenvects(:,i),... freqvector,fs,isFsSpecified); isFreqGiven = %T; end denominator = denominator + (abs(h).^2)./weights(i); end // computing pseudospectrum pspec pspec = 1.0 ./ denominator; // converting to column vector pspec = pspec(:); if ~isFreqGiven then // correcting the range of pspec according to the user specification if strcmpi(freqrange, 'onesided')==0 then if modulo(nfft,2) then // nfft is odd range = 1:(1+nfft)/2; else range = 1:((nfft/2)+1); end pspec = pspec(range); w = w(range); elseif strcmpi(freqrange,'centered')==0 then // convert two sided spectrum to centered rem = modulo(nfft,2); if rem then idx = [((nfft+1)/2+1):nfft 1:(nfft+1)/2]; else idx = [(nfft/2+2):nfft 1:(nfft/2+1)]; end pspec = pspec(idx); w = w(idx); if rem then w(1:(nfft-1)/2) = - w(nfft:-1:((nfft+1)/2+1)); else w(1:(nfft/2-1)) = - w(nfft:-1:(nfft/2+2)); end end end endfunction function [h,w] = computeFreqResponseByFFT(b,n,fs,isFsSpecified) // returns the frequency response (h) and the corresponding frequency // values (w) for a digital filter with numerator b. The evaluation of the // frequency response is done at n points in [0,fs) using fft algorithm // // Similar to MATLAB's freqz(b,a,n,'whole',fs) if isempty(fs) then fs=1; end w = linspace(0,2*%pi,n+1)'; w($) = []; w(1) = 0; // forcing the first frequency to be 0 // forcing b and a to be column vectors b = b(:); // zero padding for fft zeroPadLength = n - length(b); zeroPad = zeros(zeroPadLength,1); b = [b; zeroPad]; h = fft(b); if isFsSpecified then w = w*fs/(2*%pi); end endfunction function [h,w] = computeFreqResponseByPolyEval(b,f,fs,isFsSpecified) // returns the frequency response (h) for a digital filter with numerator b. // The evaluation of the frequency response is done at frequency values f // disp(f); // disp(isFsSpecified); f = f(:); b = b(:); n = length(b); powerMatrix = zeros(length(f),n); powerMatrix(:,1) = 1; for i=2:n powerMatrix(:,i) = exp(f*(-i+1)*%i); end h = powerMatrix*b; if isFsSpecified then w = f * fs/(2*%pi); end endfunction