summaryrefslogtreecommitdiff
path: root/macros/rootmusic.sci
diff options
context:
space:
mode:
Diffstat (limited to 'macros/rootmusic.sci')
-rw-r--r--macros/rootmusic.sci167
1 files changed, 91 insertions, 76 deletions
diff --git a/macros/rootmusic.sci b/macros/rootmusic.sci
index 34c3ff6..0efe89f 100644
--- a/macros/rootmusic.sci
+++ b/macros/rootmusic.sci
@@ -13,12 +13,12 @@ function [w,pow] = rootmusic(x,p,varargin)
// Input signal.
// If x is a vector, then it reprsenets one realization of the signal.
// If x is a matrix, then each row represents a separate observation of
- // the signal.
+ // the signal.
// p - int|double - scalar|2 element vector
- // p(1) is the signal subspace dimension and hence the number of
+ // p(1) is the signal subspace dimension and hence the number of
// complex exponentials in x.
- // p(2), if specified, represents a threshold that is multiplied by
- // the smallest estimated eigenvalue of the signal's correlation
+ // p(2), if specified, represents a threshold that is multiplied by
+ // the smallest estimated eigenvalue of the signal's correlation
// matrix.
// fs - int|double - scalar
// Sampling frequency (in Hz)
@@ -26,16 +26,31 @@ function [w,pow] = rootmusic(x,p,varargin)
// to 1 Hz
// 'corr' flag
// If specified, x is interpreted as a correlation matrix rather than
- // a matrix of the signal data. For x to be a correlation matrix,
- // x must be a square matrix and all its eigenvalues must be
+ // a matrix of the signal data. For x to be a correlation matrix,
+ // x must be a square matrix and all its eigenvalues must be
// nonnegative
//
// Examples:
// 1) 3 complex exponentials:
//
- // n=0:99;
- // s=exp(1i*pi/2*n)+2*exp(1i*pi/4*n)+exp(1i*pi/3*n)+randn(1,100);
- // [W,P] = rootmusic(s,3);
+// n=0:99;
+// s=exp(1*%i*%pi/2*n)+2*exp(1*%i*%pi/4*n)+exp(1*%i*%pi/3*n)+rand(1,100,"normal");
+// [A,R]=corrmtx(s,12,'mod');
+// [W,P] = rootmusic(R,3,'corr');
+
+
+// //2)
+// n=0:99;
+// s=exp(1*%i*%pi/2*n)+2*exp(1*%i*%pi/4*n)+exp(1*%i*%pi/3*n);
+// [A,R]=corrmtx(s,12,'mod');
+// [W,P] = rootmusic(R,3,'corr');
+
+ //EXPECTED OUTPUT:
+ //W = 0.7738111 1.5690374 1.0426234
+ //P =377.4255 103.18124 123.86659
+
+
+
//
// Author
// Ayush
@@ -44,7 +59,7 @@ function [w,pow] = rootmusic(x,p,varargin)
// corrmtx | peig | pmusic | rooteig
//
// References
- // 1) Monson H. Hayes, Statistical Digital Signal Processing And Modeling,
+ // 1) Monson H. Hayes, Statistical Digital Signal Processing And Modeling,
// Wiley & Sons, Inc, [Section 8.6.3]
//
//
@@ -52,49 +67,49 @@ function [w,pow] = rootmusic(x,p,varargin)
// w - double - vector
// Estimated frequencies of the complex sinusoids
// pow - double - vector
- // estimated absolute value squared amplitudes of the sinusoids at
- // the frequencies w
+ // estimated absolute value squared amplitudes of the sinusoids at
+ // the frequencies w
//
-
+
funcprot(0);
-
- exec('musicBase.sci',-1);
- exec('nnls.sci',-1);
-
-
+
+ //exec('/home/shashi/Desktop/FOSSEE-Signal-Processing-Toolbox-master/macros/musicBase.sci',-1);
+ //exec('/home/shashi/Desktop/FOSSEE-Signal-Processing-Toolbox-master/macros/nnls.sci',-1);
+
+
// **** checking the number of input and output arguments ****
-
+
[numOutArgs, numInArgs] = argn(0);
-
+
if numOutArgs~=1 & numOutArgs~=2 then
error(78,"rootmusic");
end
-
+
if numInArgs<1 | numInArgs>4 then
error(77,"rootmusic");
end
-
-
+
+
// **** parsing the input arguments ****
isFsSpecified = %F;
fs = [];
-
+
varargLength = length(varargin);
// searching for the 'corr' flag
isCorrFlag = %F;
-
+
if varargLength==0 then
stringIndices = [];
else
stringIndices = find(type(varargin(1:varargLength))==10);
end
-
+
if ~isempty(stringIndices) then
// ignoring all other strings except the corr flag
isCorrFlag = or(strcmpi(varargin(stringIndices),"corr")==0);
varargin(stringIndices) = [];
end
-
+
// varargin can have only an entry for fs
if length(varargin)==1 then
fs = varargin(1);
@@ -107,13 +122,13 @@ function [w,pow] = rootmusic(x,p,varargin)
isFsSpecified = %T;
elseif length(fs)>1 then
msg = "rootmusic: Wrong type for argument #4 (fs); Positive scalar expected";
- error(msg,10084);
+ error(msg,10084);
end
elseif length(varargin)>1 then
msg = "rootmusic: Wrong type for argument #4 (fs); Positive scalar expected";
- error(msg,10084);
+ error(msg,10084);
end
-
+
// extracting primary input x/R
primaryInput = x;
@@ -142,7 +157,7 @@ function [w,pow] = rootmusic(x,p,varargin)
end
// first argument of p must be an integer
if ~IsIntOrDouble(p(1),%T) then
- msg = "rootmusic: Wrong input argument #2 p(1); " + ...
+ msg = "rootmusic: Wrong input argument #2 p(1); " + ...
"positive integer expected";
error(msg,10036);
return
@@ -153,10 +168,10 @@ function [w,pow] = rootmusic(x,p,varargin)
if length(p)==2 then
if ~IsIntOrDouble(p(2),%F) then
msg = "rootmusic: Wrong type for argument #2 p(2); must be a scalar";
- error(msg,10053);
+ error(msg,10053);
end
end
-
+
isXReal = isreal(x)
if ~isCorrFlag then
// check that p(1) should be even if x is real
@@ -167,8 +182,8 @@ function [w,pow] = rootmusic(x,p,varargin)
end
end
-
-
+
+
// **** calling pmusic ****
data= struct();
data.x = primaryInput;
@@ -184,7 +199,7 @@ function [w,pow] = rootmusic(x,p,varargin)
data.isFsSpecified = isFsSpecified;
data.freqrange = "twosided";
-
+
[outData,msg] = musicBase(data);
if length(msg)~=0 then
@@ -192,52 +207,52 @@ function [w,pow] = rootmusic(x,p,varargin)
msg = "rootmusic: "+msg
error(msg);
end
-
+
pEffective = outData.pEffective;
eigenvals = outData.eigenvals;
-
+
w = computeFreqs(outData.noiseEigenvects,pEffective,%f,eigenvals);
-
+
if isempty(w) then
// assign all frequency and powers as -nan
w = %nan*(1:pEffective)';
pow = w;
return;
end
-
-
+
+
// **** Estimating the variance of the noise ****
// Estimate is the mean of the eigenvalues belonging to the noise subspace
sigma_noise = mean(eigenvals(pEffective+1:$));
-
+
pow = computePower(outData.signalEigenvects,eigenvals,w,pEffective,...
sigma_noise,isXReal);
-
-
+
+
// is fs is specified, convert normailized frequencies to actual frequencies
if isFsSpecified then
w = w*fs/(2*%pi);
end
-
-
+
+
endfunction
function w = computeFreqs(noiseEigenvects,pEffective,EVFlag,eigenvals)
- // Computes the frequencies of the complex sinusoids using the roots of
+ // Computes the frequencies of the complex sinusoids using the roots of
// the polynomial formed with the noise eigenvectors
//
// Parameters
- // noiseEigenvects -
+ // noiseEigenvects -
// A matrix where noise eigenvectors are represented by each column
- // pEffective -
+ // pEffective -
// The effective dimension of the signal subspace
- // EVFlag -
+ // EVFlag -
// Flag to indicate weighting to be used for rooteig
- // eigenvals -
+ // eigenvals -
// Eigenvals of the correlation matrix
//
// Output arguments
- // w -
+ // w -
// A vector with frequencies of the complex sinusoids
@@ -248,68 +263,68 @@ function w = computeFreqs(noiseEigenvects,pEffective,EVFlag,eigenvals)
else
weights = ones(numOfNoiseEigenvects,1);
end
-
+
// Form a polynomial consisting of a sum of polynomials given by the
- // product of the noise subspace eigenvectors and the reversed and
+ // product of the noise subspace eigenvectors and the reversed and
// conjugated version. (eq 8.163 from [1])
D = 0;
for i=1:numOfNoiseEigenvects
eigenvect = noiseEigenvects(:,i);
D = D + conv(eigenvect,conj(eigenvect($:-1:1)))./weights(i);
end
-
+
roots = roots(D);
-
+
// selecting the roots inside the unit circle
rootsSelected = roots(abs(roots)<1);
-
+
// sort the roots in order of increasing distance from the unit circle
[dist,indices] = gsort(abs(rootsSelected)-1);
-
+
sortedRoots = rootsSelected(indices);
-
+
if isempty(sortedRoots) then
w = [];
else
w = atan(imag(sortedRoots(1:pEffective)),real(sortedRoots(1:pEffective)));
end
-
-
+
+
endfunction
function power = computePower(signalEigenvects,eigenvals,w,pEffective,...
sigma_noise,isXReal)
-
+
if isXReal then
- // removing the negative frequencies as sinusoids will be present in
+ // removing the negative frequencies as sinusoids will be present in
// complex conjugate pairs
w = w(w>=0);
pEffective = length(w);
end
-
+
// Solving eq. 8.160 from [1] (Ap = b) where p is the power matrix
-
+
A = zeros(length(w),pEffective);
-
+
for i=1:pEffective
A(:,i) = computeFreqResponseByPolyEval(signalEigenvects(:,i), ...
w,1,%F);
end
-
+
A = (abs(A).^2)';
b = eigenvals(1:pEffective) - sigma_noise;
-
+
// Solving Ap=b with the constraint that all elements of p >=0
power = nnls(A,b+A*sqrt(%eps)*ones(pEffective,1));
-
-
+
+
endfunction
function h = 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
-
+
f = f(:);
b = b(:);
if isFsSpecified then
@@ -318,18 +333,18 @@ function h = computeFreqResponseByPolyEval(b,f,fs,isFsSpecified)
else
w = f;
end
-
+
n = length(b);
powerMatrix = zeros(length(f),n);
powerMatrix(:,1) = 1;
for i=2:n
powerMatrix(:,i) = exp(w*(-i+1)*%i);
end
-
+
h = powerMatrix*b;
-
-endfunction
-
+
+endfunction
+
function result = IsIntOrDouble(inputNum, isPositiveCheck)
// Checks if The Input Is Integer Or Double