File: pburg.m

package info (click to toggle)
octave-signal 1.4.6-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,280 kB
  • sloc: cpp: 2,395; ansic: 672; python: 426; makefile: 173; xml: 24
file content (173 lines) | stat: -rw-r--r-- 6,200 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
## Copyright (C) 2006 Peter V. Lanspeary <pvl@mecheng.adelaide.edu.au>
##
## This program 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.
##
## This program 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 this program; see the file COPYING. If not, see
## <https://www.gnu.org/licenses/>.

## -*- texinfo -*-
## @deftypefn {Function File} {[@var{psd},@var{f_out}] =} pburg(@var{x}, @var{poles}, @var{freq}, @var{Fs}, @var{range}, @var{method}, @var{plot_type}, @var{criterion})
## Calculate Burg maximum-entropy power spectral density.
##
## The functions "arburg" and "ar_psd" do all the work.
## See "help arburg" and "help ar_psd" for further details.
##
## ARGUMENTS:
##
##     All but the first two arguments are optional and may be empty.
##
## @table @asis
##   @item x
##   [vector] sampled data
##   @item poles
##   [integer scalar] required number of poles of the AR model
##   @item freq
##   [real vector] frequencies at which power spectral density is calculated.
##
##   [integer scalar] number of uniformly distributed frequency
##      values at which spectral density is calculated.
##      [default=256]
##   @item Fs
##   [real scalar] sampling frequency (Hertz) [default=1]
## @end table
##
## CONTROL-STRING ARGUMENTS -- each of these arguments is a character string.
##
##   Control-string arguments can be in any order after the other arguments.
##
##
## @table @asis
## @item range
##  'half',  'onesided' : frequency range of the spectrum is
##           from zero up to but not including sample_f/2.  Power
##           from negative frequencies is added to the positive
##           side of the spectrum.
##
##  'whole', 'twosided' : frequency range of the spectrum is
##           -sample_f/2 to sample_f/2, with negative frequencies
##           stored in "wrap around" order after the positive
##           frequencies; e.g. frequencies for a 10-point 'twosided'
##           spectrum are 0 0.1 0.2 0.3 0.4 0.5 -0.4 -0.3 -0.2 -0.1
##
##  'shift', 'centerdc' : same as 'whole' but with the first half
##           of the spectrum swapped with second half to put the
##           zero-frequency value in the middle. (See "help
##           fftshift". If "freq" is vector, 'shift' is ignored.
##           If model coefficients "ar_coeffs" are real, the default
##           range is 'half', otherwise default range is 'whole'.
##
## @item method
##   'fft':  use FFT to calculate power spectral density.
##
##   'poly': calculate spectral density as a polynomial of 1/z
##           N.B. this argument is ignored if the "freq" argument is a
##           vector.  The default is 'poly' unless the "freq"
##           argument is an integer power of 2.
##
## @item plot_type 
##   'plot', 'semilogx', 'semilogy', 'loglog', 'squared' or 'db':
##           specifies the type of plot.  The default is 'plot', which
##           means linear-linear axes. 'squared' is the same as 'plot'.
##           'dB' plots "10*log10(psd)".  This argument is ignored and a
##           spectrum is not plotted if the caller requires a returned
##           value.
##
## @item criterion
##   [optional string arg]  model-selection criterion.  Limits
##           the number of poles so that spurious poles are not
##           added when the whitened data has no more information
##           in it (see Kay & Marple, 1981). Recognized values are
##
##           'AKICc' -- approximate corrected Kullback information
##                     criterion (recommended),
##
##           'KIC'  -- Kullback information criterion
##
##           'AICc' -- corrected Akaike information criterion
##
##           'AIC'  -- Akaike information criterion
##
##           'FPE'  -- final prediction error" criterion
##
##           The default is to NOT use a model-selection criterion
## @end table
##
## RETURNED VALUES:
##
##     If return values are not required by the caller, the spectrum
##     is plotted and nothing is returned.
##
## @table @asis
##   @item psd
##     [real vector] power-spectral density estimate
##   @item f_out
##     [real vector] frequency values
## @end table
##
## HINTS
##
##   This function is a wrapper for arburg and ar_psd.
##
##   See "help arburg", "help ar_psd".
## @end deftypefn

function [psd,f_out]=pburg(x,poles,varargin)

  ##
  if ( nargin<2 )
    error( 'pburg: need at least 2 args. Use "help pburg"' );
  endif
  nvarargin=length(varargin);
  criterion=[];
  ##
  ## Search for a "criterion" arg. If found, remove it
  ## from "varargin" list and feed it to arburg instead.
  for iarg = 1: nvarargin
    arrgh = varargin{iarg};
    if ( ischar(arrgh) && ( strcmp(arrgh,'AKICc') ||...
         strcmp(arrgh,'KIC') || strcmp(arrgh,'AICc') ||...
         strcmp(arrgh,'AIC') || strcmp(arrgh,'FPE') ) )
      criterion=arrgh;
      if ( nvarargin>1 )
        varargin{iarg}= [];
      else
        varargin={};
      endif
    endif
  endfor
  ##
  [ar_coeffs,residual]=arburg(x,poles,criterion);
  if ( nargout==0 )
    ar_psd(ar_coeffs,residual,varargin{:});
  elseif ( nargout==1 )
    psd = ar_psd(ar_coeffs,residual,varargin{:});
  elseif ( nargout>=2 )
    [psd,f_out] = ar_psd(ar_coeffs,residual,varargin{:});
  endif

endfunction

%!demo
%! a = [1.0 -1.6216505 1.1102795 -0.4621741 0.2075552 -0.018756746];
%! Fs = 25;
%! n = 16384;
%! signal = detrend (filter (0.70181, a, rand (1, n)));
%! % frequency shift by modulating with exp(j.omega.t)
%! skewed = signal .* exp (2*pi*i*2/Fs*[1:n]);
%! hold on;
%! pburg (signal, 3, [], Fs);
%! pburg (signal, 4, [], Fs, "whole");
%! pburg (signal, 5, 128, Fs, "shift", "semilogy");
%! pburg (skewed, 7, 128, Fs, "AKICc", "shift", "semilogy");
%! user_freq = [-0.2:0.02:0.2]*Fs;
%! pburg (skewed, 7, user_freq, Fs, "AKICc", "semilogy");
%! hold off;