summaryrefslogtreecommitdiff
path: root/macros/periodogram.sci
diff options
context:
space:
mode:
Diffstat (limited to 'macros/periodogram.sci')
-rw-r--r--macros/periodogram.sci389
1 files changed, 217 insertions, 172 deletions
diff --git a/macros/periodogram.sci b/macros/periodogram.sci
index 11971d6..e2537b6 100644
--- a/macros/periodogram.sci
+++ b/macros/periodogram.sci
@@ -1,187 +1,232 @@
// Copyright (C) 2018 - IIT Bombay - FOSSEE
-//
// This file must be used under the terms of the CeCILL.
// This source file is licensed as described in the file COPYING, which
// you should have received as part of this distribution. The terms
// are also available at
// http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
-// Author:[insert name]
+// Original Source : https://octave.sourceforge.io/signal/
+// Modifieded by: Abinash Singh Under FOSSEE Internship
+// Last Modified on : Feb 2024
// Organization: FOSSEE, IIT Bombay
// Email: toolbox@scilab.in
-
-
-
-
-
function [pxx, f] = periodogram (x, varargin)
-//Calling Sequence:
-//[PXX, F] = periodogram (X, WIN, NFFT, FS)
-//[PXX, F] = periodogram (..., "RANGE")
-
-// The possible inputs are:
-//
-// X
-//
-// data vector. If X is real-valued a one-sided spectrum is
-// estimated. If X is complex-valued, or "RANGE" specifies
-// "twosided", the full spectrum is estimated.
-//
-// WIN
-// window weight data. If window is empty or unspecified a
-// default rectangular window is used. Otherwise, the window is
-// applied to the signal ('X .* WIN') before computing the
-// periodogram. The window data must be a vector of the same
-// length as X.
-//
-// NFFT
-// number of frequency bins. The default is 256 or the next
-// higher power of 2 greater than the length of X ('max (256,
-// 2.^nextpow2 (length (x)))'). If NFFT is greater than the
-// length of the input then X will be zero-padded to the length
-// of NFFT.
-//
-// FS
-// sampling rate. The default is 1.
-//
-// RANGE
-// range of spectrum. "onesided" computes spectrum from
-// [0..nfft/2+1]. "twosided" computes spectrum from [0..nfft-1].
-//
-//
-
-
-//Test cases:
-////1.
-//n=0:319;
-//x=cos(%pi/4*n)+rand(size(n,"r"),"normal");
-//[pxx,w]=periodogram(x,ones(1,320),256,2000,"onesided");
-//plot2d(w,10*log10(pxx))
-//xtitle('periodogram','frequency','magnitude(db)')
-//xgrid()
-//
-//
-
-[nargout,nargin]=argn();
- // check input arguments
- if (nargin < 1 | nargin > 5)
- error("wrong no. of input arguments")
- end
-
- nfft = [];
- fs = [];
- ran = [];
- win = [];
- j = 2;
- for k = 1:length (varargin)
- if (type (varargin(k))==10)
- ran = varargin(k);
- else
- select (j)
- case 2
- win = varargin(k);
- case 3
- nfft = varargin(k);
- case 4
- fs = varargin(k);
+ //Calling Sequence:
+ //[PXX, F] = periodogram (X, WIN, NFFT, FS)
+ //[PXX, F] = periodogram (..., "RANGE")
+ // The possible inputs are:
+ //
+ // X
+ //
+ // data vector. If X is real-valued a one-sided spectrum is
+ // estimated. If X is complex-valued, or "RANGE" specifies
+ // "twosided", the full spectrum is estimated.
+ //
+ // WIN
+ // window weight data. If window is empty or unspecified a
+ // default rectangular window is used. Otherwise, the window is
+ // applied to the signal ('X .* WIN') before computing the
+ // periodogram. The window data must be a vector of the same
+ // length as X.
+ //
+ // NFFT
+ // number of frequency bins. The default is 256 or the next
+ // higher power of 2 greater than the length of X ('max (256,
+ // 2.^nextpow2 (length (x)))'). If NFFT is greater than the
+ // length of the input then X will be zero-padded to the length
+ // of NFFT.
+ //
+ // FS
+ // sampling rate. The default is 1.
+ //
+ // RANGE
+ // range of spectrum. "onesided" computes spectrum from
+ // [0..nfft/2+1]. "twosided" computes spectrum from [0..nfft-1].
+ //
+ //
+ // Dependencies
+ // hamming fft1
+
+ [nargout,nargin]=argn();
+ // check input arguments
+ if (nargin < 1 | nargin > 5)
+ error("wrong no. of input arguments")
end
- j=j+1;
- end
- end
-
- if (~ isvector (x))
- error ("periodogram: X must be a real or complex vector");
- end
- x = x(:); // Use column vectors from now on
-
- n = size(x,"r");
-
- if (~isempty (win))
- if (~ isvector (win) | length (win) ~= n)
- error ("periodogram: WIN must be a vector of the same length as X");
- end
- win = win(:);
- x =x.* win;
-else
- win=window("re",length(x));
- win=win(:);
- x=x.*win;
-
- end
-
- if (isempty (nfft))
- nfft = max (256, 2.^nextpow2 (n));
- elseif (~ isscalar (nfft))
- error ("periodogram: NFFT must be a scalar");
- end
-
- use_w_freq = isempty (fs);
- if (~use_w_freq & ~ isscalar (fs))
- error ("periodogram: FS must be a scalar");
- end
-
- if (~strcmpi (ran, "onesided"))
- ran = 1;
- elseif (~strcmpi (ran, "twosided"))
- ran = 2;
- elseif (~strcmpi (ran, "centered"))
- error ('periodogram: centered ran type is not implemented');
- else
- ran = 2-isreal (x);
- end
-
- // compute periodogram
-
- if (n > nfft)
- Pxx = 0;
- rr = modulo(length (x), nfft);
- if (rr)
- x = [x(:); zeros(nfft-rr, 1)];
- end
- x = sum (matrix (x, nfft,length(x)/nfft), 2);
- end
-
- if (~ isempty (win))
- n = sum(win.*conj(win));
- end;
- Pxx = (abs (fft (x))) .^ 2 / n;
-
- if (use_w_freq)
- Pxx =Pxx/ 2*%pi;
- else
- Pxx =Pxx/ fs;
- end
-
- // generate output arguments
-
- if (ran == 1) // onesided
- if (modulo (nfft,2)==0) // nfft is even
- psd_len = nfft/2+1;
- Pxx = Pxx(1:psd_len) + [0; Pxx(nfft:-1:psd_len+1); 0];
- else // nfft is odd
- psd_len = (nfft+1)/2;
- Pxx = Pxx(1:psd_len) + [0; Pxx(nfft:-1:psd_len+1)];
- end
- end
-
- if (nargout ~= 1)
- if (ran == 1)
- f = (0:nfft/2)' / nfft;
- elseif (ran == 2)
- f = (0:nfft-1)' / nfft;
- end
- if (use_w_freq)
- f =f* 2*pi; // generate w=2*pi*f
+
+ nfft = [];
+ fs = [];
+ ran = "";
+ win = [];
+ j = 2;
+ for k = 1:length (varargin)
+ if (type (varargin(k))==10)
+ ran = varargin(k);
+ else
+ select (j)
+ case 2
+ win = varargin(k);
+ case 3
+ nfft = varargin(k);
+ case 4
+ fs = varargin(k);
+ end
+ j=j+1;
+ end
+ end
+
+ if (~ isvector (x))
+ error ("periodogram: X must be a real or complex vector");
+ end
+ x = x(:); // Use column vectors from now on
+
+ n = size(x,1);
+
+ if (~isempty (win))
+ if (~ isvector (win) | length (win) ~= n)
+ error ("periodogram: WIN must be a vector of the same length as X");
+ end
+ win = win(:);
+ x =x.* win;
else
- f =f* fs;
+ win=window("re",length(x));
+ win=win(:);
+ x=x.*win;
+
+ end
+
+ if (isempty (nfft))
+ nfft = max (256, 2.^nextpow2 (n));
+ elseif (~ isscalar (nfft))
+ error ("periodogram: NFFT must be a scalar");
+ end
+
+ use_w_freq = isempty (fs);
+ if (~use_w_freq & ~ isscalar (fs))
+ error ("periodogram: FS must be a scalar");
+ end
+
+ if (~strcmp (ran, "onesided"))
+ ran = 1;
+ elseif (~strcmp (ran, "twosided"))
+ ran = 2;
+ elseif (~strcmp (ran, "centered"))
+ error ('periodogram: centered ran type is not implemented');
+ else
+ ran = 2 - double(isreal (x));
+ end
+
+ // compute periodogram
+
+ if (n > nfft)
+ Pxx = 0;
+ rr = modulo(length(x), nfft);
+ if (rr)
+ x = [x(:); zeros(nfft-rr, 1)];
+ end
+ x = sum (matrix (x, nfft,-1), 2);
+ end
+
+ if (~ isempty (win))
+ n = sum(win.*conj(win));
+ end;
+
+ Pxx = (abs (fft1 (x,nfft))) .^ 2 / n;
+
+ if (use_w_freq)
+ Pxx =Pxx/(2*%pi);
+ else
+ Pxx =Pxx/fs;
+ end
+
+ // generate output arguments
+
+ if (ran == 1) // onesided
+ if (modulo(nfft,2)==0) // nfft is even
+ psd_len = (nfft/2)+1;
+ Pxx = Pxx(1:psd_len) + [0; Pxx(nfft:-1:psd_len+1); 0];
+ else // nfft is odd
+ psd_len = (nfft+1)/2;
+ Pxx = Pxx(1:psd_len) + [0; Pxx(nfft:-1:psd_len+1)];
+ end
+ end
+
+ //if (nargout() ~= 1) FIXME: fix nargout
+ if (ran == 1)
+ f = (0:nfft/2)' / nfft;
+ elseif (ran == 2)
+ f = (0:nfft-1)' / nfft;
+ end
+ if (use_w_freq)
+ f =f* 2*%pi; // generate w=2*pi*f
+ else
+ f =f* fs;
+ end
+ //end
+ if (nargout() ~= 2)
+ if (use_w_freq)
+ plot (f/(2*%pi), 10*log10 (Pxx));
+ xlabel ("normalized frequency [x pi rad]");
+ ylabel ("Power density [dB/rad/sample]");
+ else
+ plot (f, 10*log10 (Pxx));
+ xlabel ("frequency [Hz]");
+ ylabel ("Power density [dB/Hz]");
+ end
+ title ("Periodogram Power Spectral Density Estimate");
end
- end
-
-
-
pxx = Pxx;
-
-
-
-
endfunction
+
+/*
+pi = %pi; // ezecute on scilab only
+
+t = 0:0.01:1;
+x = sin(2*pi*10*t);
+periodogram(x);
+
+x = complex(0:0.01:1, 0:0.01:1);
+periodogram(x);
+
+x = cos(0:0.01:1);
+win = hamming(101);
+periodogram(x, win);
+
+
+
+x = tan(0:0.01:1);
+nfft = 512;
+periodogram(x, [], nfft);
+
+
+t = 0:0.01:1;
+x = sin(2*pi*10*t);
+Fs = 100;
+periodogram(x, [], [], Fs)
+
+
+
+x = sin(0:0.01:1);
+periodogram(x, [], [], [], 'onesided');
+
+x = sin(0:0.01:1);
+periodogram(x, [], [], [], 'twosided')
+
+
+Fs = 1000;
+t = 0:1/Fs:1-1/Fs;
+f0 = 100;
+x = sin(2*pi*f0*t);
+[Pxx, f] = periodogram(x, [], [], Fs);
+[_, idx] = max(Pxx);
+detected_freq = f(idx);
+
+
+// Test error : invalid window length
+x = randn(100,1);
+win = hamming(50);
+periodogram(x, win)
+
+// Test invalid nfft (negative)
+periodogram(x, [], -256)
+
+*/