]> Creatis software - CreaPhase.git/blobdiff - octave_packages/m/signal/periodogram.m
update packages
[CreaPhase.git] / octave_packages / m / signal / periodogram.m
diff --git a/octave_packages/m/signal/periodogram.m b/octave_packages/m/signal/periodogram.m
new file mode 100644 (file)
index 0000000..7c26ad4
--- /dev/null
@@ -0,0 +1,190 @@
+## Copyright (C) 1995-2012 Friedrich Leisch
+## Copyright (C) 2010 Alois Schloegl
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {[Pxx, @var{w}] =} periodogram (@var{x})
+## For a data matrix @var{x} from a sample of size @var{n}, return the
+## periodogram.  The angular frequency is returned in @var{w}.
+##
+## [Pxx,w] = periodogram (@var{x}).
+##
+## [Pxx,w] = periodogram (@var{x},win).
+##
+## [Pxx,w] = periodogram (@var{x},win,nfft).
+##
+## [Pxx,f] = periodogram (@var{x},win,nfft,Fs).
+##
+## [Pxx,f] = periodogram (@var{x},win,nfft,Fs,"range").
+##
+## @itemize
+## @item x: data; if real-valued a one-sided spectrum is estimated,
+## if complex-valued or range indicates "@nospell{twosided}", the full
+## spectrum is estimated.
+##
+## @item win: weight data with window, x.*win is used for further computation,
+## if window is empty, a rectangular window is used.
+##
+## @item nfft: number of frequency bins, default max(256, 2.^ceil(log2(length(x)))).
+##
+## @item Fs: sampling rate, default 1.
+##
+## @item range: "@nospell{onesided}" computes spectrum from [0..nfft/2+1].
+## "@nospell{twosided}" computes spectrum from [0..nfft-1].  These strings
+## can appear at any position in the list input arguments after window.
+##
+## @item Pxx: one-, or two-sided power spectrum.
+##
+## @item w: angular frequency [0..2*pi) (two-sided) or [0..pi] one-sided.
+##
+## @item f: frequency [0..Fs) (two-sided) or [0..Fs/2] one-sided.
+## @end itemize
+## @end deftypefn
+
+## Author: FL <Friedrich.Leisch@ci.tuwien.ac.at>
+## Description: Compute the periodogram
+
+function [pxx, f] = periodogram (x, varargin)
+
+  ## check input arguments
+
+  if (nargin < 1 || nargin > 5)
+    print_usage ();
+  endif
+
+  nfft = []; fs = []; range = []; window = [];
+  j = 1;
+  for k = 1:length (varargin)
+    if (ischar (varargin{k}))
+      range = varargin{k};
+    else
+      switch (j)
+      case 1
+        window = varargin{k};
+      case 2
+        nfft   = varargin{k};
+      case 3
+        fs     = varargin{k};
+      case 4
+        range  = varargin{k};
+      endswitch
+      j++;
+    endif
+  endfor
+
+  [r, c] = size (x);
+  if (r == 1)
+    r = c;
+  endif
+
+  if (ischar (window))
+    range = window;
+    window = [];
+  endif;
+  if (ischar (nfft))
+    range = nfft;
+    nfft = [];
+  endif;
+  if (ischar (fs))
+    range = fs;
+    fs = [];
+  endif;
+
+  if (!  isempty (window))
+    if (all (size (x) == size (window)))
+      x .*= window;
+    elseif (size (x, 1) == size (window, 1) && size (window, 2) == 1)
+      x .*= window (:,ones (1,c));
+    endif;
+  endif
+
+  if (numel (nfft)>1)
+    error ("nfft must be scalar");
+  endif
+  if (isempty (nfft))
+    nfft = max (256, 2.^ceil (log2 (r)));
+  endif
+
+  if (strcmp (range, "onesided"))
+    range = 1;
+  elseif strcmp (range, "twosided")
+    range = 2;
+  else
+    range = 2-isreal (x);
+  endif
+
+  ## compute periodogram
+
+  if (r>nfft)
+    Pxx = 0;
+    rr = rem (length (x), nfft);
+    if (rr)
+      x = [x(:); (zeros (nfft-rr, 1))];
+    endif
+    x = sum (reshape (x, nfft, []), 2);
+  endif
+
+  if (isempty (window))
+    n = r;
+  else
+    n = sumsq (window);
+  end;
+  Pxx = (abs (fft (x, nfft))) .^ 2 / n ;
+
+  if (nargin<4)
+    Pxx /= 2*pi;
+  elseif (! isempty (fs))
+    Pxx /= fs;
+  endif
+
+  ## generate output arguments
+
+  if (range == 1)  # onesided
+    Pxx = Pxx(1:nfft/2+1) + [0; Pxx(end:-1:(nfft/2+2)); 0];
+  endif
+
+  if (nargout != 1)
+    if (range == 1)
+      f = (0:nfft/2)'/nfft;
+    elseif (range == 2)
+      f = (0:nfft-1)'/nfft;
+    endif
+    if (nargin<4)
+      f *= 2*pi; # generate w=2*pi*f
+    elseif (! isempty (fs))
+      f *= fs;
+    endif
+  endif
+
+  if (nargout == 0)
+    if (nargin<4)
+      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]");
+    endif
+    grid on;
+    title ("Periodogram Power Spectral Density Estimate");
+  else
+    pxx = Pxx;
+  endif
+
+endfunction