├── src ├── by_hand_code │ ├── __init__.py │ ├── covar.py │ ├── acm.py │ ├── covm.py │ ├── convm.py │ ├── pade.py │ ├── impz.py │ ├── kalman.py │ ├── convmtx.py │ ├── system_example.py │ ├── prony_test.py │ ├── prony.py │ ├── prony_matlab.py │ ├── prony_testing.py │ ├── lms.py │ └── stmbc.py ├── matlabpipetest.py ├── convmtx_matlab_vs_python.py ├── stmcb_matlab_vs_python.py ├── matcompat.py ├── invfreqs_matlab_vs_python.py ├── arburg_matlab_vs_python.py ├── prony_matlab_vs_python.py ├── trashbin │ ├── convmtx.py │ ├── system_example.py │ └── prony_testing.py ├── stmcb_matlab_vs_python_2.py ├── aryule_matlab_vs_python.py ├── arcov_matlab_vs_python.py ├── armcov_matlab_vs_python.py ├── invfreqs.py ├── arcov.py ├── armcov.py ├── prony.py ├── arparest.py ├── aryule.py ├── stmcb.py ├── convmtx.py └── arburg.py ├── .project ├── .pydevproject ├── matlab_test_files ├── system_example_matlab.m ├── system_example_matlab.py ├── arcov.m ├── armcov.m ├── convmtx.m ├── arcov.py ├── convmtx_test.m ├── armcov.py ├── prony_testing.m ├── prony.m ├── prony_to_py.m ├── convmtx_test.py ├── prony_test2.m ├── aryule.m ├── aryule_test.m ├── stmcb.m ├── prony_test.m ├── prony_to_py.py ├── aryule_test.py ├── stmcb_to_py.m ├── arparest.m ├── stmcb_test.m ├── arparest_test.m ├── arburg.m ├── arburg_test.m ├── arburg_test2.m ├── arburg_test.py ├── arburg.py ├── arburg_test2.py ├── stmcb_to_py.py ├── arparest_test.py ├── invfreqz.m ├── invfreqz_test.m └── invfreqs.m ├── LICENSE └── README.md /src/by_hand_code/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | parametric_modeling 4 | 5 | 6 | 7 | 8 | 9 | org.python.pydev.PyDevBuilder 10 | 11 | 12 | 13 | 14 | 15 | org.python.pydev.pythonNature 16 | 17 | 18 | -------------------------------------------------------------------------------- /.pydevproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | /${PROJECT_DIR_NAME}/src 5 | 6 | python 2.7 7 | Default 8 | 9 | -------------------------------------------------------------------------------- /matlab_test_files/system_example_matlab.m: -------------------------------------------------------------------------------- 1 | syst_fake=tf([1],[1 2 3]) 2 | syst_fake_dis=c2d(syst_fake,0.01) 3 | [output,t]=step(syst_fake_dis) 4 | plot(output) 5 | 6 | out_len = length(output) 7 | input=1:out_len; 8 | input(:)=1; 9 | [num,den]=stmcb_test(output,input,0,2); 10 | sys_model=tf(num,den,0.01) 11 | step(sys_model) 12 | hold on 13 | step(syst_fake) 14 | 15 | 16 | % [b,a] = butter(6,0.2); % Butterworth filter design 17 | % h = filter(b,a,[1 zeros(1,100)]); % Filter data using above filter 18 | % [bb,aa] = stmcb_test(h,4,4) 19 | -------------------------------------------------------------------------------- /matlab_test_files/system_example_matlab.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | import scipy 4 | import matcompat 5 | 6 | # if available import pylab (from matlibplot) 7 | try: 8 | import matplotlib.pylab as plt 9 | except ImportError: 10 | pass 11 | 12 | syst_fake = tf(np.array(np.hstack((1.))), np.array(np.hstack((1., 2., 3.)))) 13 | syst_fake_dis = c2d(syst_fake, 0.01) 14 | [output, t] = plt.step(syst_fake_dis) 15 | plt.plot(output) 16 | out_len = length(output) 17 | input = np.arange(1., (out_len)+1) 18 | input[:] = 1. 19 | [num, den] = stmcb_test(output, input, 0., 2.) 20 | #% sys_model=tf(num,den,0.01) 21 | #% step(sys_model) 22 | #% hold on 23 | #% step(syst_fake) -------------------------------------------------------------------------------- /src/matlabpipetest.py: -------------------------------------------------------------------------------- 1 | from matlabpipe import MatlabPipe 2 | 3 | 4 | def test_t_tide_demo(matlab): 5 | """Call Matlab and run t_tide demos.""" 6 | cmd = """[b,a] = butter(6,0.2); % Butterworth filter design 7 | h = filter(b,a,[1 zeros(1,100)]); % Filter data using above filter 8 | [bb,aa] = stmcb(h,4,4); 9 | """ 10 | out = matlab.eval(cmd) 11 | print "Printing output" 12 | print out 13 | print "bb is:" 14 | bb = matlab.get('bb') 15 | print bb 16 | del(out) 17 | 18 | if __name__ == '__main__': 19 | matlab = MatlabPipe(matlab_version='2013a') 20 | matlab.open() 21 | test_t_tide_demo(matlab) 22 | 23 | -------------------------------------------------------------------------------- /matlab_test_files/arcov.m: -------------------------------------------------------------------------------- 1 | function [a,e] = arcov( x, p) 2 | %ARCOV AR parameter estimation via covariance method. 3 | % A = ARCOV(X,ORDER) returns the polynomial A corresponding to the AR 4 | % parametric signal model estimate of vector X using the Covariance method. 5 | % ORDER is the model order of the AR system. 6 | % 7 | % [A,E] = ARCOV(...) returns the variance estimate E of the white noise 8 | % input to the AR model. 9 | % 10 | % See also PCOV, ARMCOV, ARBURG, ARYULE, LPC, PRONY. 11 | 12 | % Ref: S. Kay, MODERN SPECTRAL ESTIMATION, 13 | % Prentice-Hall, 1988, Chapter 7 14 | % P. Stoica and R. Moses, INTRODUCTION TO SPECTRAL ANALYSIS, 15 | % Prentice-Hall, 1997, Chapter 3 16 | 17 | % Author(s): R. Losada and P. Pacheco 18 | % Copyright 1988-2002 The MathWorks, Inc. 19 | % $Revision: 1.13.4.3 $ $Date: 2011/05/13 18:06:51 $ 20 | 21 | error(nargchk(2,2,nargin,'struct')); 22 | 23 | [a,e,msg,msgobj] = arparest(x,p,'covariance'); 24 | if ~isempty(msg), error(msgobj); end 25 | 26 | % [EOF] - arcov.m 27 | -------------------------------------------------------------------------------- /matlab_test_files/armcov.m: -------------------------------------------------------------------------------- 1 | function [a,e] = armcov( x, p) 2 | %ARMCOV AR parameter estimation via modified covariance method. 3 | % A = ARMCOV(X,ORDER) returns the polynomial A corresponding to the AR 4 | % parametric signal model estimate of vector X using the Modified Covariance 5 | % method. ORDER is the model order of the AR system. 6 | % 7 | % [A,E] = ARMCOV(...) returns the variance estimate E of the white noise 8 | % input to the AR model. 9 | % 10 | % See also PMCOV, ARCOV, ARBURG, ARYULE, LPC, PRONY. 11 | 12 | % References: 13 | % [1] S. Lawrence Marple, DIGITAL SPECTRAL ANALYSIS WITH APPLICATIONS, 14 | % Prentice-Hall, 1987, Chapter 8 15 | % [2] Steven M. Kay, MODERN SPECTRAL ESTIMATION THEORY & APPLICATION, 16 | % Prentice-Hall, 1988, Chapter 7 17 | 18 | % Author(s): R. Losada and P. Pacheco 19 | % Copyright 1988-2002 The MathWorks, Inc. 20 | % $Revision: 1.13.4.3 $ $Date: 2011/05/13 18:06:53 $ 21 | 22 | error(nargchk(2,2,nargin,'struct')); 23 | 24 | [a,e,msg,msgobj] = arparest(x,p,'modified'); 25 | if ~isempty(msg), error(msgobj); end 26 | 27 | % [EOF] - armcov.m 28 | -------------------------------------------------------------------------------- /src/by_hand_code/covar.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ This file is a Python translation of the MATLAB file covar.m 3 | 4 | Python version by RDL 14 Feb 2012 5 | Copyright notice from covar.m: 6 | copyright 1996, by M.H. Hayes. For use with the book 7 | "Statistical Digital Signal Processing and Modeling" 8 | (John Wiley & Sons, 1996). 9 | """ 10 | 11 | import numpy as np 12 | import convm 13 | 14 | def covar(x, p): 15 | """Generates a covariance matrix 16 | 17 | Usage: X = covar(x,p) 18 | Generates a p x p covariance matrix for the sequence x. 19 | 20 | """ 21 | x = x[:] 22 | m = len(x) 23 | x = x - np.ones(m) * np.sum(x) / m 24 | 25 | R = np.dot(convm.convm(x, p).conj().T, convm.convm(x, p)) / (m-1) 26 | 27 | return R 28 | 29 | #x = x(:); 30 | #m = length(x); 31 | #x = x - ones(m,1)*(sum(x)/m); 32 | #R = convm(x,p)'*convm(x,p)/(m-1); 33 | #end; 34 | 35 | def main(): 36 | """Just a test driver, compare with Hayes pp. 572-573""" 37 | x = np.array([1, 3, 2]) 38 | X = covar(x,4) 39 | print(X) 40 | 41 | # X = np.cov(x, rowvar=0) 42 | # print(X) 43 | 44 | if __name__ == '__main__': 45 | main() 46 | 47 | -------------------------------------------------------------------------------- /matlab_test_files/convmtx.m: -------------------------------------------------------------------------------- 1 | function t = convmtx(v,n) 2 | %CONVMTX Convolution matrix. 3 | % CONVMTX(C,N) returns the convolution matrix for vector C. 4 | % If C is a column vector and X is a column vector of length N, 5 | % then CONVMTX(C,N)*X is the same as CONV(C,X). 6 | % If R is a row vector and X is a row vector of length N, 7 | % then X*CONVMTX(R,N) is the same as CONV(R,X). 8 | % 9 | % % Example: 10 | % % Generate a simple convolution matrix. 11 | % 12 | % h = [1 2 3 2 1]; 13 | % convmtx(h,7) % Convolution matrix 14 | % 15 | % See also CONV. 16 | 17 | % Author(s): L. Shure, 5-17-88 18 | % T. Krauss, 3-30-93, removed dependence on toeplitz 19 | % Copyright 1988-2004 The MathWorks, Inc. 20 | % $Revision: 1.6.4.3 $ $Date: 2012/10/29 19:30:54 $ 21 | 22 | [mv,nv] = size(v); 23 | v = v(:); % make v a column vector 24 | 25 | % t = toeplitz([v; zeros(n-1,1)],zeros(n,1)); put Toeplitz code inline 26 | c = [v; zeros(n-1,1)]; 27 | r = zeros(n,1); 28 | m = length(c); 29 | x = [r(n:-1:2) ; c(:)]; % build vector of user data 30 | % 31 | cidx = (0:m-1)'; 32 | ridx = n:-1:1; 33 | t = cidx(:,ones(n,1)) + ridx(ones(m,1),:); % Toeplitz subscripts 34 | t(:) = x(t); % actual data 35 | % end of toeplitz code 36 | 37 | if mv < nv 38 | t = t.'; 39 | end 40 | 41 | -------------------------------------------------------------------------------- /src/convmtx_matlab_vs_python.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Jan 22 17:18 2014 5 | 6 | @author: Sammy Pfeiffer 7 | @email: sammypfeiffer@gmail.com 8 | 9 | Test our python cnvmtx vs the MatlabTM cnvmtx 10 | """ 11 | from matlabpipe import MatlabPipe 12 | import numpy as np 13 | from convmtx import convmtx 14 | 15 | OKGREEN = '\033[92m' 16 | FAIL = '\033[91m' 17 | ENDC = '\033[0m' 18 | 19 | if __name__ == '__main__': 20 | matlab = MatlabPipe(matlab_version='2013a') 21 | matlab.open() 22 | 23 | cmd = """h = [1 2 3 2 1]; 24 | c_matrix = convmtx(h,7);""" 25 | out = matlab.eval(cmd) 26 | # Get matlab inputs 27 | matlab_h = matlab.get('h') 28 | # Get matlab output of convmtx 29 | matlab_c_matrix = matlab.get('c_matrix') 30 | 31 | 32 | # Use same inputs on python convmtx 33 | vertical_h = np.vstack((matlab_h)) 34 | py_c_matrix = convmtx(vertical_h,7) 35 | 36 | # Check if we get the same result 37 | print "\nMatlab c_matrix vs Python c_matrix" 38 | if np.allclose(matlab_c_matrix, py_c_matrix): # see if they are equal with relative tolerance=1e-05 and abs tol=1e-08 39 | print OKGREEN + "Coincident results!" + ENDC 40 | else: 41 | print FAIL +"Different results..." + ENDC 42 | print matlab_c_matrix 43 | print py_c_matrix 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/by_hand_code/acm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ This file is a Python translation of the MATLAB file acm.m 3 | 4 | Python version by RDL 29 Mar 2012 5 | Copyright notice from acm.m: 6 | copyright 1996, by M.H. Hayes. For use with the book 7 | "Statistical Digital Signal Processing and Modeling" 8 | (John Wiley & Sons, 1996). 9 | """ 10 | from __future__ import print_function,division 11 | import numpy as np 12 | from convm import convm 13 | 14 | def acm(x,p): 15 | """ Find an all-pole model using the autocorrelation method 16 | 17 | Usage: a,err = acm(x,p) 18 | 19 | The input sequence x is modeled as the unit sample response of 20 | a filter having a system function of the form 21 | H(z) = b(0)/A(z) 22 | where the coefficients of A(z) are contained in the vector 23 | a=[1, a(1), ... a(p)] 24 | The input p defines the number of poles in the model. 25 | The modeling error is returned in err. 26 | The numerator b(0) is typically set equal to the square 27 | root of err. 28 | """ 29 | x = x.flatten() 30 | N = len(x) 31 | if p > N: 32 | print('ERROR: model order too large') 33 | else: 34 | X = convm(x, p+1) 35 | Xq = X[0:N+p-1,0:p] 36 | xq1 = -X[1:N+p, 0] 37 | a = np.linalg.lstsq(Xq, xq1)[0] 38 | a = np.insert(a, 0, 1) 39 | err = np.dot(X[0:N+p,0].conj().T, X) 40 | err = np.dot(err, a) 41 | err = np.abs(err) 42 | return a, err 43 | 44 | -------------------------------------------------------------------------------- /matlab_test_files/arcov.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | import scipy 4 | import matcompat 5 | 6 | # if available import pylab (from matlibplot) 7 | try: 8 | import matplotlib.pylab as plt 9 | except ImportError: 10 | pass 11 | 12 | def arcov(x, p): 13 | 14 | # Local Variables: a, msgobj, p, msg, x, e 15 | # Function calls: nargchk, arcov, nargin, isempty, error, arparest 16 | #%ARCOV AR parameter estimation via covariance method. 17 | #% A = ARCOV(X,ORDER) returns the polynomial A corresponding to the AR 18 | #% parametric signal model estimate of vector X using the Covariance method. 19 | #% ORDER is the model order of the AR system. 20 | #% 21 | #% [A,E] = ARCOV(...) returns the variance estimate E of the white noise 22 | #% input to the AR model. 23 | #% 24 | #% See also PCOV, ARMCOV, ARBURG, ARYULE, LPC, PRONY. 25 | #% Ref: S. Kay, MODERN SPECTRAL ESTIMATION, 26 | #% Prentice-Hall, 1988, Chapter 7 27 | #% P. Stoica and R. Moses, INTRODUCTION TO SPECTRAL ANALYSIS, 28 | #% Prentice-Hall, 1997, Chapter 3 29 | #% Author(s): R. Losada and P. Pacheco 30 | #% Copyright 1988-2002 The MathWorks, Inc. 31 | #% $Revision: 1.13.4.3 $ $Date: 2011/05/13 18:06:51 $ 32 | matcompat.error(nargchk(2., 2., nargin, 'struct')) 33 | [a, e, msg, msgobj] = arparest(x, p, 'covariance') 34 | if not isempty(msg): 35 | matcompat.error(msgobj) 36 | 37 | 38 | #% [EOF] - arcov.m 39 | return [a, e] -------------------------------------------------------------------------------- /matlab_test_files/convmtx_test.m: -------------------------------------------------------------------------------- 1 | function t = convmtx(v,n) 2 | %CONVMTX Convolution matrix. 3 | % CONVMTX(C,N) returns the convolution matrix for vector C. 4 | % If C is a column vector and X is a column vector of length N, 5 | % then CONVMTX(C,N)*X is the same as CONV(C,X). 6 | % If R is a row vector and X is a row vector of length N, 7 | % then X*CONVMTX(R,N) is the same as CONV(R,X). 8 | % 9 | % % Example: 10 | % % Generate a simple convolution matrix. 11 | % 12 | % h = [1 2 3 2 1]; 13 | % convmtx(h,7) % Convolution matrix 14 | % 15 | % See also CONV. 16 | 17 | % Author(s): L. Shure, 5-17-88 18 | % T. Krauss, 3-30-93, removed dependence on toeplitz 19 | % Copyright 1988-2004 The MathWorks, Inc. 20 | % $Revision: 1.6.4.3 $ $Date: 2012/10/29 19:30:54 $ 21 | 22 | [mv,nv] = size(v) 23 | v 24 | v = v(:); % make v a column vector 25 | v 26 | toep_left = [v; zeros(n-1,1)] 27 | toep_right = zeros(n,1) 28 | 29 | t = toeplitz([v; zeros(n-1,1)],zeros(n,1)) 30 | t 31 | c = [v; zeros(n-1,1)]; 32 | r = zeros(n,1); 33 | m = length(c); 34 | x_left = r(n:-1:2); 35 | x_right = c(:); 36 | x = [x_left; x_right] 37 | %x = [r(n:-1:2) ; c(:)]; % build vector of user data 38 | 39 | cidx = (0:m-1)' 40 | ridx = n:-1:1 41 | t = cidx(:,ones(n,1)) + ridx(ones(m,1),:) % Toeplitz subscripts 42 | t(:) = x(t); % actual data 43 | % end of toeplitz code 44 | mv 45 | nv 46 | lol = 1 47 | t 48 | lol2 = 2 49 | if mv < nv 50 | mv 51 | nv 52 | display('transposing...') 53 | t = t.'; 54 | end 55 | 56 | -------------------------------------------------------------------------------- /src/by_hand_code/covm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ This file is a Python translation of the MATLAB file covm.m 3 | 4 | Python version by RDL 31 Mar 2012 5 | Copyright notice from covm.m: 6 | copyright 1996, by M.H. Hayes. For use with the book 7 | "Statistical Digital Signal Processing and Modeling" 8 | (John Wiley & Sons, 1996). 9 | """ 10 | from __future__ import print_function,division 11 | import numpy as np 12 | from convm import convm 13 | 14 | def covm(x, p): 15 | """ Find an all-pole model using the covariance method 16 | 17 | USAGE: a,err = covm(x,p) 18 | 19 | An all-pole of order p is found for the input sequence 20 | x using the covariance method. The model is of the form 21 | H(z) = b(0)/A(z) 22 | The coefficients of A(z) are returned in the vector 23 | a=[1, a(1), ... a(p)] 24 | and the modeling error is returned in err. 25 | 26 | """ 27 | x = x.flatten() 28 | N = len(x) 29 | if p > N: 30 | print('ERROR: model order too large') 31 | else: 32 | X = convm(x, p+1) 33 | Xq = X[p-1:N-1,0:p] 34 | xq1 = -X[p:N, 0] 35 | a = np.linalg.lstsq(Xq, xq1)[0] 36 | a = np.insert(a, 0, 1) 37 | err = np.dot(X[p:N,0].conj().T, X[p:N,:]) 38 | # Added by RDL: it seems that in order to have the sample 39 | # autocorrelation, you have to normalize by the number of samples used, 40 | # which in this case is (N-p) 41 | err /= (N-p) 42 | err = np.dot(err, a) 43 | err = np.abs(err) 44 | return a, err 45 | -------------------------------------------------------------------------------- /matlab_test_files/armcov.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | import scipy 4 | import matcompat 5 | 6 | # if available import pylab (from matlibplot) 7 | try: 8 | import matplotlib.pylab as plt 9 | except ImportError: 10 | pass 11 | 12 | def armcov(x, p): 13 | 14 | # Local Variables: a, msgobj, p, msg, x, e 15 | # Function calls: nargchk, nargin, isempty, error, arparest, armcov 16 | #%ARMCOV AR parameter estimation via modified covariance method. 17 | #% A = ARMCOV(X,ORDER) returns the polynomial A corresponding to the AR 18 | #% parametric signal model estimate of vector X using the Modified Covariance 19 | #% method. ORDER is the model order of the AR system. 20 | #% 21 | #% [A,E] = ARMCOV(...) returns the variance estimate E of the white noise 22 | #% input to the AR model. 23 | #% 24 | #% See also PMCOV, ARCOV, ARBURG, ARYULE, LPC, PRONY. 25 | #% References: 26 | #% [1] S. Lawrence Marple, DIGITAL SPECTRAL ANALYSIS WITH APPLICATIONS, 27 | #% Prentice-Hall, 1987, Chapter 8 28 | #% [2] Steven M. Kay, MODERN SPECTRAL ESTIMATION THEORY & APPLICATION, 29 | #% Prentice-Hall, 1988, Chapter 7 30 | #% Author(s): R. Losada and P. Pacheco 31 | #% Copyright 1988-2002 The MathWorks, Inc. 32 | #% $Revision: 1.13.4.3 $ $Date: 2011/05/13 18:06:53 $ 33 | matcompat.error(nargchk(2., 2., nargin, 'struct')) 34 | [a, e, msg, msgobj] = arparest(x, p, 'modified') 35 | if not isempty(msg): 36 | matcompat.error(msgobj) 37 | 38 | 39 | #% [EOF] - armcov.m 40 | return [a, e] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, Sammy Pfeiffer 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /src/stmcb_matlab_vs_python.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Jan 22 17:18 2014 5 | 6 | @author: Sammy Pfeiffer 7 | @email: sammypfeiffer@gmail.com 8 | 9 | Test our python stmcb vs the MatlabTM stmcb 10 | """ 11 | from matlabpipe import MatlabPipe 12 | import numpy as np 13 | from stmcb import stmcb 14 | 15 | OKGREEN = '\033[92m' 16 | FAIL = '\033[91m' 17 | ENDC = '\033[0m' 18 | 19 | if __name__ == '__main__': 20 | matlab = MatlabPipe(matlab_version='2013a') 21 | matlab.open() 22 | 23 | cmd = """[b,a] = butter(6,0.2); 24 | h = filter(b,a,[1 zeros(1,100)]); 25 | [bb,aa] = stmcb(h,4,4);""" 26 | out = matlab.eval(cmd) 27 | # Get matlab inputs 28 | matlab_b = matlab.get('b') 29 | matlab_a = matlab.get('a') 30 | matlab_h = matlab.get('h') 31 | # Get matlab output of stmcb 32 | matlab_bb = matlab.get('bb') 33 | matlab_aa = matlab.get('aa') 34 | 35 | # Use same inputs on python stmcb 36 | [py_bb, py_aa] = stmcb(matlab_h,4,4) 37 | 38 | # Check if we get the same result 39 | print "\nMatlab bb vs Python bb" 40 | if np.allclose(matlab_bb, py_bb): # see if they are equal with relative tolerance=1e-05 and abs tol=1e-08 41 | print OKGREEN + "Coincident results!" + ENDC 42 | else: 43 | print FAIL +"Different results..." + ENDC 44 | print matlab_bb 45 | print py_bb 46 | 47 | print "\nMatlab matlab_aa vs Python py_aa" 48 | if np.allclose(matlab_aa, py_aa): 49 | print OKGREEN + "Coincident results!" + ENDC 50 | else: 51 | print FAIL +"Different results..." + ENDC 52 | print matlab_aa 53 | print py_aa 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/matcompat.py: -------------------------------------------------------------------------------- 1 | # LiberMate 2 | # 3 | # Copyright (C) 2009 Eric C. Schug 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program. If not, see . 17 | # 18 | 19 | __author__ = "Eric C. Schug (schugschug@gmail.com)" 20 | __copyright__ = "Copyright (c) 2009 Eric C. Schug" 21 | __license__ = "GNU General Public License" 22 | __revision__ = "$Id$" 23 | 24 | #import numpy as np 25 | #import scipy 26 | #import matcompat 27 | 28 | # if available import pylab (from matlibplot) 29 | # try: 30 | # import matplotlib.pylab as plt 31 | # except ImportError: 32 | # pass 33 | 34 | import types 35 | 36 | #does structure have attribute/field name 37 | def isfield(struct,name): 38 | return hasattr(struct,name) 39 | 40 | 41 | class MatError(Exception): 42 | pass 43 | 44 | def error(mesg): 45 | raise MatError, mesg 46 | 47 | class MatWarning(UserWarning): 48 | pass 49 | 50 | def warning(mesg): 51 | raise MatWarning, mesg 52 | 53 | def length(x): 54 | len(x.flatten()) 55 | 56 | def size(mat, elem=None): 57 | if not elem: 58 | return mat.shape 59 | else: 60 | return mat.shape[int(elem)-1] 61 | -------------------------------------------------------------------------------- /src/invfreqs_matlab_vs_python.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Jan 22 16:56 2014 5 | 6 | @author: Sammy Pfeiffer 7 | @email: sammypfeiffer@gmail.com 8 | 9 | Test our python invfreqs vs the MatlabTM invfreqs 10 | """ 11 | from matlabpipe import MatlabPipe 12 | import numpy as np 13 | from invfreqs import invfreqs 14 | 15 | OKGREEN = '\033[92m' 16 | FAIL = '\033[91m' 17 | ENDC = '\033[0m' 18 | 19 | if __name__ == '__main__': 20 | matlab = MatlabPipe(matlab_version='2013a') 21 | matlab.open() 22 | 23 | cmd = """b = [1 2 3 2 3]; 24 | a = [1 2 3 2 1 4]; 25 | [h,w] = freqs(b,a,64); 26 | [bb,aa] = invfreqs(h,w,4,5)""" 27 | out = matlab.eval(cmd) 28 | # Get matlab inputs 29 | matlab_b = matlab.get('b') 30 | matlab_a = matlab.get('a') 31 | matlab_h = matlab.get('h') 32 | matlab_w = matlab.get('w') 33 | # Get matlab output of invfreqs 34 | matlab_bb = matlab.get('bb') 35 | matlab_aa = matlab.get('aa') 36 | 37 | # Use same inputs on python invfreqs 38 | [py_bb, py_aa] = invfreqs(matlab_h, matlab_w, 4, 5) 39 | 40 | # Check if we get the same result 41 | print "\nMatlab bb vs Python bb" 42 | if np.allclose(matlab_bb, py_bb): # see if they are equal with relative tolerance=1e-05 and abs tol=1e-08 43 | print OKGREEN + "Coincident results!" + ENDC 44 | else: 45 | print FAIL +"Different results..." + ENDC 46 | print matlab_bb 47 | print py_bb 48 | 49 | print "\nMatlab Den vs Python Den" 50 | if np.allclose(matlab_aa, py_aa): 51 | print OKGREEN + "Coincident results!" + ENDC 52 | else: 53 | print FAIL +"Different results..." + ENDC 54 | print matlab_aa 55 | print py_aa 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/arburg_matlab_vs_python.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Jan 22 17:18 2014 5 | 6 | @author: Sammy Pfeiffer 7 | 8 | Test our python arburg vs the MatlabTM arburg 9 | """ 10 | from matlabpipe import MatlabPipe 11 | import numpy as np 12 | from arburg import arburg 13 | 14 | OKGREEN = '\033[92m' 15 | FAIL = '\033[91m' 16 | ENDC = '\033[0m' 17 | 18 | if __name__ == '__main__': 19 | matlab = MatlabPipe(matlab_version='2013a') 20 | matlab.open() 21 | 22 | cmd = """input = [0 1 2 3 4 5] 23 | [ar_coeffs, NoiseVariance] = arburg(input, 4)""" 24 | out = matlab.eval(cmd) 25 | # Get matlab inputs 26 | matlab_input = matlab.get('input') 27 | # Get matlab output of stmcb 28 | matlab_ar_coeffs = matlab.get('ar_coeffs') 29 | matlab_NoiseVariance = matlab.get('NoiseVariance') 30 | #matlab_sys_model = matlab.get('sys_model') 31 | 32 | # Use same inputs on python stmcb 33 | [py_ar_coeffs, py_NoiseVariance] = arburg(matlab_input, 4) 34 | 35 | # Check if we get the same result 36 | print "\nMatlab ar_coeffs vs Python ar_coeffs" 37 | if np.allclose(matlab_ar_coeffs, py_ar_coeffs): # see if they are equal with relative tolerance=1e-05 and abs tol=1e-08 38 | print OKGREEN + "Coincident results!" + ENDC 39 | else: 40 | print FAIL +"Different results..." + ENDC 41 | print matlab_ar_coeffs 42 | print py_ar_coeffs 43 | 44 | print "\nMatlab NoiseVariance vs Python NoiseVariance" 45 | if np.allclose(matlab_NoiseVariance, py_NoiseVariance): 46 | print OKGREEN + "Coincident results!" + ENDC 47 | else: 48 | print FAIL +"Different results..." + ENDC 49 | print matlab_NoiseVariance 50 | print py_NoiseVariance 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/by_hand_code/convm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ This file is a Python translation of the MATLAB file convm.m 3 | 4 | Python version by RDL 10 Jan 2012 5 | Copyright notice from convm.m: 6 | copyright 1996, by M.H. Hayes. For use with the book 7 | "Statistical Digital Signal Processing and Modeling" 8 | (John Wiley & Sons, 1996). 9 | """ 10 | 11 | import numpy as np 12 | 13 | def convm(x, p): 14 | """Generates a convolution matrix 15 | 16 | Usage: X = convm(x,p) 17 | Given a vector x of length N, an N+p-1 by p convolution matrix is 18 | generated of the following form: 19 | | x(0) 0 0 ... 0 | 20 | | x(1) x(0) 0 ... 0 | 21 | | x(2) x(1) x(0) ... 0 | 22 | X = | . . . . | 23 | | . . . . | 24 | | . . . . | 25 | | x(N) x(N-1) x(N-2) ... x(N-p+1) | 26 | | 0 x(N) x(N-1) ... x(N-p+2) | 27 | | . . . . | 28 | | . . . . | 29 | | 0 0 0 ... x(N) | 30 | 31 | That is, x is assumed to be causal, and zero-valued after N. 32 | 33 | """ 34 | N = len(x) + 2*p - 2 35 | xpad = np.concatenate([np.zeros(p-1), x[:], np.zeros(p-1)]) 36 | X = np.zeros((len(x)+p-1, p)) 37 | # Construct X column by column 38 | for i in xrange(p): 39 | X[:,i] = xpad[p-i-1:N-i] 40 | 41 | return X 42 | 43 | def main(): 44 | """Just a test driver, compare with Hayes pp. 572-573""" 45 | x = np.array([1, 3, 2]) 46 | X = convm(x,4) 47 | print(X) 48 | 49 | if __name__ == '__main__': 50 | main() 51 | 52 | -------------------------------------------------------------------------------- /src/prony_matlab_vs_python.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Jan 22 16:56 2014 5 | 6 | @author: Sammy Pfeiffer 7 | @email: sammypfeiffer@gmail.com 8 | 9 | Test our python prony vs the MatlabTM prony 10 | """ 11 | from matlabpipe import MatlabPipe 12 | import numpy as np 13 | from prony import prony 14 | 15 | OKGREEN = '\033[92m' 16 | FAIL = '\033[91m' 17 | ENDC = '\033[0m' 18 | 19 | if __name__ == '__main__': 20 | matlab = MatlabPipe(matlab_version='2013a') 21 | matlab.open() 22 | 23 | cmd = """[b,a] = butter(4,0.2); 24 | impulseResp = impz(b,a); 25 | denOrder=4; 26 | numOrder=4; 27 | [Num,Den]=prony(impulseResp,numOrder,denOrder);""" 28 | out = matlab.eval(cmd) 29 | # Get matlab inputs 30 | matlab_impulseResp = matlab.get('impulseResp') 31 | matlab_denOrder = matlab.get('denOrder') 32 | matlab_numOrder = matlab.get('numOrder') 33 | # Get matlab output of prony 34 | matlab_Num = matlab.get('Num') 35 | matlab_Den = matlab.get('Den') 36 | 37 | # Use same inputs on python prony 38 | [py_Num, py_Den] = prony(matlab_impulseResp,matlab_numOrder,matlab_denOrder) 39 | 40 | # Check if we get the same result 41 | print "\nMatlab Num vs Python Num" 42 | if np.allclose(matlab_Num, py_Num): # see if they are equal with relative tolerance=1e-05 and abs tol=1e-08 43 | print OKGREEN + "Coincident results!" + ENDC 44 | else: 45 | print FAIL +"Different results..." + ENDC 46 | print matlab_Num 47 | print py_Num 48 | 49 | print "\nMatlab Den vs Python Den" 50 | if np.allclose(matlab_Den, py_Den): 51 | print OKGREEN + "Coincident results!" + ENDC 52 | else: 53 | print FAIL +"Different results..." + ENDC 54 | print matlab_Den 55 | print py_Den 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /matlab_test_files/prony_testing.m: -------------------------------------------------------------------------------- 1 | %% testing prony function versus python function 2 | % % Example: 3 | % % Fit an IIR model to an impulse response of a lowpass filter. 4 | % 5 | [b,a] = butter(4,0.2); 6 | % # b = 0.0048 0.0193 0.0289 0.0193 0.0048 7 | % # a = 1.0000 -2.3695 2.3140 -1.0547 0.1874 8 | b 9 | a 10 | impulseResp = impz(b,a); % obtain impulse response 11 | impulseResp 12 | % impulseResp = 13 | % 14 | % 0.0048 15 | % 0.0307 16 | % 0.0906 17 | % 0.1679 18 | % 0.2246 19 | % 0.2335 20 | % 0.1935 21 | % 0.1238 22 | % 0.0496 23 | % -0.0085 24 | % -0.0407 25 | % -0.0476 26 | % -0.0369 27 | % -0.0186 28 | % -0.0013 29 | % 0.0100 30 | % 0.0140 31 | % 0.0121 32 | % 0.0071 33 | % 0.0017 34 | % -0.0022 35 | % -0.0040 36 | % -0.0039 37 | % -0.0026 38 | % -0.0010 39 | % 0.0004 40 | % 0.0011 41 | % 0.0012 42 | % 0.0009 43 | % 0.0004 44 | % 0.0000 45 | % -0.0003 46 | % -0.0004 47 | % -0.0003 48 | % -0.0002 49 | % -0.0000 50 | % 0.0001 51 | % 0.0001 52 | % 0.0001 53 | % 0.0001 54 | % 0.0000 55 | % -0.0000 56 | % -0.0000 57 | % python [0.00482434335771622,0.0307287177680857,0.0905946819548826,0.167944821844737,0.224641271344028] 58 | denOrder=4; numOrder=4; % system function of order 4 59 | [Num,Den]=prony_test(impulseResp,numOrder,denOrder); 60 | % Num =0.0048 0.0193 0.0289 0.0193 0.0048 61 | % Den =1.0000 -2.3695 2.3140 -1.0547 0.1874 62 | display('Num') 63 | Num 64 | display('Den') 65 | Den 66 | % subplot(211); % impulse response and input 67 | % stem(impz(Num,Den,length(impulseResp))); 68 | % title('Impulse Response with Prony Design'); 69 | % subplot(212); 70 | % stem(impulseResp); title('Input Impulse Response'); -------------------------------------------------------------------------------- /src/trashbin/convmtx.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | import scipy 4 | import matcompat 5 | from matcompat import * 6 | 7 | 8 | def convmtx(v, n): 9 | 10 | # Local Variables: cidx, c, x_left, ridx, m, n, x_right, mv, t, v, x, r, nv 11 | # Function calls: convmtx, length, ones, zeros, size 12 | #%CONVMTX Convolution matrix. 13 | #% CONVMTX(C,N) returns the convolution matrix for vector C. 14 | #% If C is a column vector and X is a column vector of length N, 15 | #% then CONVMTX(C,N)*X is the same as CONV(C,X). 16 | #% If R is a row vector and X is a row vector of length N, 17 | #% then X*CONVMTX(R,N) is the same as CONV(R,X). 18 | #% 19 | #% % Example: 20 | #% % Generate a simple convolution matrix. 21 | #% 22 | #% h = [1 2 3 2 1]; 23 | #% convmtx(h,7) % Convolution matrix 24 | #% 25 | #% See also CONV. 26 | #% Author(s): L. Shure, 47-88 27 | #% T. Krauss, 3-30-93, removed dependence on toeplitz 28 | #% Copyright 1988-2004 The MathWorks, Inc. 29 | #% $Revision: 1.6.4.3 $ $Date: 2012/10/29 19:30:54 $ 30 | [mv, nv] = matcompat.size(v) 31 | v = v.flatten(1) 32 | #% make v a column vector 33 | #% t = toeplitz([v; zeros(n-1,1)],zeros(n,1)); put Toeplitz code inline 34 | c = np.array(np.vstack((np.hstack((v)), np.hstack((np.zeros((n-1.), 1.)))))) 35 | r = np.zeros(n, 1.) 36 | m = length(c) 37 | x_left = r[int(n)-1:2.:-1.] 38 | x_right = c.flatten(1) 39 | x = np.array(np.vstack((np.hstack((x_left)), np.hstack((x_right))))) 40 | #%x = [r(n:-1:2) ; c(:)]; % build vector of user data 41 | cidx = np.arange(0., (m-1.)+1).conj().T 42 | ridx = np.arange(n, (1.)+(-1.), -1.) 43 | t = cidx[:,int(np.ones(n, 1.))-1]+ridx[int(np.ones(m, 1.))-1,:] 44 | #% Toeplitz subscripts 45 | t[:] = x[int(t)-1] 46 | #% actual data 47 | #% end of toeplitz code 48 | if mv N) 49 | H(:,(N+2):(K+1)) = []; 50 | end 51 | % Partition H matrix 52 | H1 = H(1:(M+1),:); % M+1 by N+1 53 | h1 = H((M+2):(K+1),1); % K-M by 1 54 | H2 = H((M+2):(K+1),2:(N+1)); % K-M by N 55 | a = [1; -H2\h1].'; 56 | b = c*a*H1.'; 57 | 58 | -------------------------------------------------------------------------------- /matlab_test_files/prony_to_py.m: -------------------------------------------------------------------------------- 1 | function [b,a] = prony(h, nb ,na) 2 | %PRONY Prony's method for time-domain IIR filter design. 3 | % [B,A] = PRONY(H, NB, NA) finds a filter with numerator order 4 | % NB, denominator order NA, and having the impulse response in 5 | % vector H. The IIR filter coefficients are returned in 6 | % length NB+1 and NA+1 row vectors B and A, ordered in 7 | % descending powers of Z. H may be real or complex. 8 | % 9 | % If the largest order specified is greater than the length of H, 10 | % H is padded with zeros. 11 | % 12 | % % Example: 13 | % % Fit an IIR model to an impulse response of a lowpass filter. 14 | % 15 | % [b,a] = butter(4,0.2); 16 | % impulseResp = impz(b,a); % obtain impulse response 17 | % denOrder=4; numOrder=4; % system function of order 4 18 | % [Num,Den]=prony(impulseResp,numOrder,denOrder); 19 | % subplot(211); % impulse response and input 20 | % stem(impz(Num,Den,length(impulseResp))); 21 | % title('Impulse Response with Prony Design'); 22 | % subplot(212); 23 | % stem(impulseResp); title('Input Impulse Response'); 24 | % 25 | % See also STMCB, LPC, BUTTER, CHEBY1, CHEBY2, ELLIP, INVFREQZ. 26 | 27 | % Author(s): L. Shure, 5-17-88 28 | % L. Shure, 12-17-90, revised 29 | % Copyright 1988-2012 The MathWorks, Inc. 30 | % $Revision: 1.7.4.1.2.1 $ $Date: 2013/01/02 17:47:48 $ 31 | 32 | % References: 33 | % [1] T.W. Parks and C.S. Burrus, Digital Filter Design, 34 | % John Wiley and Sons, 1987, p226. 35 | 36 | K = length(h) - 1; 37 | M = nb; N = na; 38 | if K <= max(M,N) % zero-pad input if necessary 39 | K = max(M,N)+1; 40 | h(K+1) = 0; 41 | end 42 | c = h(1); 43 | if c==0 % avoid divide by zero 44 | c=1; 45 | end 46 | H = toeplitz(h/c,[1 zeros(1,K)]); 47 | % K+1 by N+1 48 | if (K > N) 49 | H(:,(N+2):(K+1)) = []; 50 | end 51 | % Partition H matrix 52 | H1 = H(1:(M+1),:); % M+1 by N+1 53 | h1 = H((M+2):(K+1),1); % K-M by 1 54 | H2 = H((M+2):(K+1),2:(N+1)); % K-M by N 55 | H2_minus = -H2; 56 | a = [1; H2_minus\h1].'; 57 | b = c*a*H1.'; 58 | -------------------------------------------------------------------------------- /src/stmcb_matlab_vs_python_2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Jan 22 17:18 2014 5 | 6 | @author: Sammy Pfeiffer 7 | @email: sammypfeiffer@gmail.com 8 | 9 | Test our python stmcb vs the MatlabTM stmcb 10 | """ 11 | from matlabpipe import MatlabPipe 12 | import numpy as np 13 | from stmcb import stmcb 14 | 15 | OKGREEN = '\033[92m' 16 | FAIL = '\033[91m' 17 | ENDC = '\033[0m' 18 | 19 | if __name__ == '__main__': 20 | matlab = MatlabPipe(matlab_version='2013a') 21 | matlab.open() 22 | 23 | cmd = """syst_fake=tf([1],[1 2 3]); 24 | syst_fake_dis=c2d(syst_fake,0.01); 25 | [output,t]=step(syst_fake_dis); 26 | out_len = length(output); 27 | input=1:out_len; 28 | input(:)=1; 29 | [num,den]=stmcb(output,input,0,2); 30 | sys_model=tf(num,den,0.01);""" 31 | out = matlab.eval(cmd) 32 | # Get matlab inputs 33 | #matlab_syst_fake = matlab.get('syst_fake') 34 | #matlab_syst_fake_dis = matlab.get('syst_fake_dis') 35 | matlab_output = matlab.get('output') 36 | matlab_t = matlab.get('t') 37 | matlab_out_len = matlab.get('out_len') 38 | matlab_input = matlab.get('input') 39 | # Get matlab output of stmcb 40 | matlab_num = matlab.get('num') 41 | matlab_den = matlab.get('den') 42 | #matlab_sys_model = matlab.get('sys_model') 43 | 44 | # Use same inputs on python stmcb 45 | [py_num, py_den] = stmcb(matlab_output,matlab_input,0,2) 46 | 47 | # Check if we get the same result 48 | print "\nMatlab num vs Python num" 49 | if np.allclose(matlab_num, py_num): # see if they are equal with relative tolerance=1e-05 and abs tol=1e-08 50 | print OKGREEN + "Coincident results!" + ENDC 51 | else: 52 | print FAIL +"Different results..." + ENDC 53 | print matlab_num 54 | print py_num 55 | 56 | print "\nMatlab den vs Python den" 57 | if np.allclose(matlab_den, py_den): 58 | print OKGREEN + "Coincident results!" + ENDC 59 | else: 60 | print FAIL +"Different results..." + ENDC 61 | print matlab_den 62 | print py_den 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /matlab_test_files/convmtx_test.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | import scipy 4 | import matcompat 5 | 6 | # if available import pylab (from matlibplot) 7 | try: 8 | import matplotlib.pylab as plt 9 | except ImportError: 10 | pass 11 | 12 | def convmtx(v, n): 13 | 14 | # Local Variables: cidx, c, x_left, ridx, m, n, x_right, mv, t, v, x, r, nv 15 | # Function calls: convmtx, length, ones, zeros, size, toeplitz 16 | #%CONVMTX Convolution matrix. 17 | #% CONVMTX(C,N) returns the convolution matrix for vector C. 18 | #% If C is a column vector and X is a column vector of length N, 19 | #% then CONVMTX(C,N)*X is the same as CONV(C,X). 20 | #% If R is a row vector and X is a row vector of length N, 21 | #% then X*CONVMTX(R,N) is the same as CONV(R,X). 22 | #% 23 | #% % Example: 24 | #% % Generate a simple convolution matrix. 25 | #% 26 | #% h = [1 2 3 2 1]; 27 | #% convmtx(h,7) % Convolution matrix 28 | #% 29 | #% See also CONV. 30 | #% Author(s): L. Shure, 47-88 31 | #% T. Krauss, 3-30-93, removed dependence on toeplitz 32 | #% Copyright 1988-2004 The MathWorks, Inc. 33 | #% $Revision: 1.6.4.3 $ $Date: 2012/10/29 19:30:54 $ 34 | [mv, nv] = matcompat.size(v) 35 | v = v.flatten(1) 36 | #% make v a column vector 37 | #t = toeplitz(np.array(np.vstack((np.hstack((v)), np.hstack((np.zeros((n-1.), 1.)))))), np.zeros(n, 1.)) 38 | c = np.array(np.vstack((np.hstack((v)), np.hstack((np.zeros((n-1.), 1.)))))) 39 | r = np.zeros(n, 1.) 40 | m = length(c) 41 | x_left = r[int(n)-1:2.:-1.] 42 | x_right = c.flatten(1) 43 | x = np.array(np.vstack((np.hstack((x_left)), np.hstack((x_right))))) 44 | #%x = [r(n:-1:2) ; c(:)]; % build vector of user data 45 | cidx = np.arange(0., (m-1.)+1).conj().T 46 | ridx = np.arange(n, (1.)+(-1.), -1.) 47 | t = cidx[:,int(np.ones(n, 1.))-1]+ridx[int(np.ones(m, 1.))-1,:] 48 | #% Toeplitz subscripts 49 | t[:] = x[int(t)-1] 50 | #% actual data 51 | #% end of toeplitz code 52 | if mv N) 51 | H(:,(N+2):(K+1)) = []; 52 | end 53 | % Partition H matrix 54 | H1 = H(1:(M+1),:); % M+1 by N+1 55 | h1 = H((M+2):(K+1),1); % K-M by 1 56 | H2 = H((M+2):(K+1),2:(N+1)); % K-M by N 57 | a = [1; -H2\h1].'; 58 | b = c*a*H1.'; 59 | 60 | -------------------------------------------------------------------------------- /matlab_test_files/aryule.m: -------------------------------------------------------------------------------- 1 | function [a,e,k] = aryule( x, p) 2 | %ARYULE AR parameter estimation via Yule-Walker method. 3 | % A = ARYULE(X,ORDER) returns the polynomial A corresponding to the AR 4 | % parametric signal model estimate of vector X using the Yule-Walker 5 | % (autocorrelation) method. ORDER is the model order of the AR system. 6 | % This method solves the Yule-Walker equations by means of the Levinson- 7 | % Durbin recursion. 8 | % 9 | % [A,E] = ARYULE(...) returns the final prediction error E (the variance 10 | % estimate of the white noise input to the AR model). 11 | % 12 | % [A,E,K] = ARYULE(...) returns the vector K of reflection coefficients. 13 | % 14 | % % Example: 15 | % % Estimate model order using decay of reflection coefficients. 16 | % 17 | % rng default; 18 | % y=filter(1,[1 -0.75 0.5],0.2*randn(1024,1)); 19 | % 20 | % % Create AR(2) process 21 | % [ar_coeffs,NoiseVariance,reflect_coeffs]=aryule(y,10); 22 | % 23 | % % Fit AR(10) model 24 | % stem(reflect_coeffs); axis([-0.05 10.5 -1 1]); 25 | % title('Reflection Coefficients by Lag'); xlabel('Lag'); 26 | % ylabel('Reflection Coefficent'); 27 | % 28 | % See also PYULEAR, ARMCOV, ARBURG, ARCOV, LPC, PRONY. 29 | 30 | % Ref: S. Orfanidis, OPTIMUM SIGNAL PROCESSING, 2nd Ed. 31 | % Macmillan, 1988, Chapter 5 32 | % M. Hayes, STATISTICAL DIGITAL SIGNAL PROCESSING AND MODELING, 33 | % John Wiley & Sons, 1996, Chapter 8 34 | 35 | % Author(s): R. Losada 36 | % Copyright 1988-2004 The MathWorks, Inc. 37 | % $Revision: 1.12.4.6 $ $Date: 2012/10/29 19:30:38 $ 38 | 39 | error(nargchk(2,2,nargin,'struct')) 40 | 41 | % Check the input data type. Single precision is not supported. 42 | try 43 | chkinputdatatype(x,p); 44 | catch ME 45 | throwAsCaller(ME); 46 | end 47 | 48 | [mx,nx] = size(x); 49 | if isempty(x) || length(x) < p || min(mx,nx) > 1, 50 | error(message('signal:aryule:InvalidDimensions')); 51 | elseif isempty(p) || ~(p == round(p)) 52 | error(message('signal:aryule:MustBeInteger')) 53 | end 54 | if issparse(x) 55 | error(message('signal:aryule:Sparse')) 56 | end 57 | 58 | R = xcorr(x,p,'biased'); 59 | [a,e,k] = levinson(R(p+1:end),p); 60 | 61 | 62 | -------------------------------------------------------------------------------- /matlab_test_files/aryule_test.m: -------------------------------------------------------------------------------- 1 | function [a,e,k] = aryule( x, p) 2 | %ARYULE AR parameter estimation via Yule-Walker method. 3 | % A = ARYULE(X,ORDER) returns the polynomial A corresponding to the AR 4 | % parametric signal model estimate of vector X using the Yule-Walker 5 | % (autocorrelation) method. ORDER is the model order of the AR system. 6 | % This method solves the Yule-Walker equations by means of the Levinson- 7 | % Durbin recursion. 8 | % 9 | % [A,E] = ARYULE(...) returns the final prediction error E (the variance 10 | % estimate of the white noise input to the AR model). 11 | % 12 | % [A,E,K] = ARYULE(...) returns the vector K of reflection coefficients. 13 | % 14 | % % Example: 15 | % % Estimate model order using decay of reflection coefficients. 16 | % 17 | % rng default; 18 | % y=filter(1,[1 -0.75 0.5],0.2*randn(1024,1)); 19 | % 20 | % % Create AR(2) process 21 | % [ar_coeffs,NoiseVariance,reflect_coeffs]=aryule(y,10); 22 | % 23 | % % Fit AR(10) model 24 | % stem(reflect_coeffs); axis([-0.05 10.5 -1 1]); 25 | % title('Reflection Coefficients by Lag'); xlabel('Lag'); 26 | % ylabel('Reflection Coefficent'); 27 | % 28 | % See also PYULEAR, ARMCOV, ARBURG, ARCOV, LPC, PRONY. 29 | 30 | % Ref: S. Orfanidis, OPTIMUM SIGNAL PROCESSING, 2nd Ed. 31 | % Macmillan, 1988, Chapter 5 32 | % M. Hayes, STATISTICAL DIGITAL SIGNAL PROCESSING AND MODELING, 33 | % John Wiley & Sons, 1996, Chapter 8 34 | 35 | % Author(s): R. Losada 36 | % Copyright 1988-2004 The MathWorks, Inc. 37 | % $Revision: 1.12.4.6 $ $Date: 2012/10/29 19:30:38 $ 38 | 39 | error(nargchk(2,2,nargin,'struct')) 40 | 41 | % Check the input data type. Single precision is not supported. 42 | %try 43 | % chkinputdatatype(x,p); 44 | %catch ME 45 | % throwAsCaller(ME); 46 | %end 47 | 48 | [mx,nx] = size(x); 49 | if isempty(x) || length(x) < p || min(mx,nx) > 1, 50 | error(message('signal:aryule:InvalidDimensions')); 51 | elseif isempty(p) || ~(p == round(p)) 52 | error(message('signal:aryule:MustBeInteger')) 53 | end 54 | if issparse(x) 55 | error(message('signal:aryule:Sparse')) 56 | end 57 | 58 | R = xcorr(x,p,'biased'); 59 | [a,e,k] = levinson(R(p+1:end),p); 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/by_hand_code/pade.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ This file is a Python translation of the MATLAB file pade.m 3 | 4 | Python version by RDL 10 Jan 2012 5 | Copyright notice from pade.m: 6 | copyright 1996, by M.H. Hayes. For use with the book 7 | "Statistical Digital Signal Processing and Modeling" 8 | (John Wiley & Sons, 1996). 9 | """ 10 | 11 | import sys 12 | import numpy as np 13 | 14 | from convm import convm 15 | 16 | def pade(x, p, q): 17 | """Model a signal using the Padé approximation method 18 | 19 | Usage: [a,b] = pade(x,p,q) 20 | 21 | The input sequence x is modeled as the unit sample response of 22 | a filter having a system function of the form 23 | H(z) = B(z)/A(z) 24 | The polynomials B(z) and A(z) are formed from the vectors 25 | b=[b(0), b(1), ... b(q)] 26 | a=[1 , a(1), ... a(p)] 27 | The input q defines the number of zeros in the model 28 | and p defines the number of poles. 29 | 30 | This comes from Hayes, p. 138 31 | 32 | """ 33 | if p+q >= len(x): 34 | print('ERROR: model order too large') 35 | sys.exit(1) 36 | 37 | # Set up the convolution matrices 38 | X = convm(x[:], p+1) 39 | Xq = X[q+1:q+p+1, 1:p+1] 40 | 41 | # Solve for the denominator coefficients 42 | if p>0: 43 | a = -np.linalg.lstsq(Xq, x[q+1:q+p+1])[0] 44 | a = np.insert(a, 0, 1) 45 | else: 46 | a = np.array(1) 47 | 48 | # Solve for the numerator coefficients 49 | b = np.dot(X[0:q+1,0:p+1], a) 50 | 51 | return (a.flatten(),b.flatten()) 52 | 53 | #function [a,b] = pade(x,p,q) 54 | #x = x(:); 55 | #X = convm(x,p+1); 56 | #Xq = X(q+2:q+p+1,2:p+1); 57 | #a = [1;-Xq\X(q+2:q+p+1,1)]; 58 | #b = X(1:q+1,1:p+1)*a; 59 | 60 | 61 | def main(): 62 | """Just a test driver, compare with Hayes pp. 138-140""" 63 | x = np.array([1, 1.5, 0.75, 0.375, 0.1875, 0.0938]) 64 | pq_array = [(2,0), (0,2), (1,1)] 65 | for i in xrange(len(pq_array)): 66 | p,q = pq_array[i] 67 | print('For p={} q={}:'.format(p,q)) 68 | a,b = pade(x, p, q) 69 | print('a: {}\nb: {}'.format(a,b)) 70 | 71 | if __name__ == '__main__': 72 | main() 73 | 74 | -------------------------------------------------------------------------------- /src/aryule_matlab_vs_python.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Jan 22 22:26 2014 5 | 6 | @author: Sammy Pfeiffer 7 | @email: sammypfeiffer@gmail.com 8 | 9 | Test our python aryule vs the MatlabTM aryule 10 | 11 | MATLAB testing code from: 12 | http://www.music.mcgill.ca/~gary/307/matlab/predict.m 13 | """ 14 | from matlabpipe import MatlabPipe 15 | import numpy as np 16 | from aryule import aryule 17 | 18 | OKGREEN = '\033[92m' 19 | FAIL = '\033[91m' 20 | ENDC = '\033[0m' 21 | 22 | if __name__ == '__main__': 23 | matlab = MatlabPipe(matlab_version='2013a') 24 | matlab.open() 25 | 26 | cmd = """A=[1 -2.7607 3.8106 -2.6535 0.9238]; 27 | y=filter(1,A,0.2*randn(1024,1)); 28 | [ar_coeffs, e, k]=aryule(y,4);""" 29 | out = matlab.eval(cmd) 30 | # Get matlab inputs 31 | matlab_A = matlab.get('A') 32 | matlab_y = matlab.get('y') 33 | # Get matlab output of aryule 34 | matlab_ar_coeffs = matlab.get('ar_coeffs') 35 | matlab_e = matlab.get('e') 36 | matlab_k = matlab.get('k') 37 | 38 | 39 | # Use same inputs on python aryule 40 | [py_ar_coeffs, py_e, py_k] = aryule(matlab_y, 4) 41 | 42 | # Check if we get the same result 43 | print "\nMatlab ar_coeffs vs Python ar_coeffs" 44 | if np.allclose(matlab_ar_coeffs, py_ar_coeffs): # see if they are equal with relative tolerance=1e-05 and abs tol=1e-08 45 | print OKGREEN + "Coincident results!" + ENDC 46 | else: 47 | print FAIL +"Different results..." + ENDC 48 | print matlab_ar_coeffs 49 | print py_ar_coeffs 50 | 51 | 52 | print "\nMatlab e vs Python e" 53 | if np.allclose(matlab_e, py_e): # see if they are equal with relative tolerance=1e-05 and abs tol=1e-08 54 | print OKGREEN + "Coincident results!" + ENDC 55 | else: 56 | print FAIL +"Different results..." + ENDC 57 | print matlab_e 58 | print py_e 59 | 60 | print "\nMatlab k vs Python k" 61 | if np.allclose(matlab_k, py_k): # see if they are equal with relative tolerance=1e-05 and abs tol=1e-08 62 | print OKGREEN + "Coincident results!" + ENDC 63 | else: 64 | print FAIL +"Different results..." + ENDC 65 | print matlab_k 66 | print py_k 67 | -------------------------------------------------------------------------------- /src/by_hand_code/impz.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sun Jan 5 17:48:01 2014 5 | 6 | @author: Sammy Pfeiffer 7 | This file contains a python implementation of impz matlab function 8 | """ 9 | from scipy import zeros 10 | from scipy.signal import lfilter 11 | import numpy as np 12 | 13 | def impz(b,a): 14 | """Pseudo implementation of the impz method of MATLAB""" 15 | #% Compute time vector 16 | # M = 0; NN = []; 17 | # if isempty(N) 18 | # % if not specified, determine the length 19 | # if isTF 20 | # N = impzlength(b,a,.00005); 21 | # else 22 | # N = impzlength(b,.00005); 23 | # end 24 | p = np.roots(a) 25 | N = stableNmarginal_length(p, 0.00005, 0) 26 | N = len(b) * len(b) * len(b) # MATLAB AUTOFINDS THE SIZE HERE... 27 | #TODO: Implement some way of finding the autosieze of this... I used a couple of examples... matlab gave 43 as length we give 64 28 | x = zeros(N) 29 | x[0] = 1 30 | h = lfilter(b,a, x) 31 | return h 32 | 33 | 34 | def stableNmarginal_length(p, tol, delay): 35 | """ % Determine the length for an unstable filter 36 | %minimum height is .00005 original amplitude:""" 37 | 38 | # ind = find(abs(p-1)<1e-5); # does nothing in our example case 39 | # p(ind) = -p(ind); % treat constant as Nyquist # does nothing 40 | # ind = find(abs(abs(p)-1)<1e-5); # does nothing too... 41 | # periods = 5*max(2*pi./abs(angle(p(ind)))); % five periods 42 | # p(ind) = []; % get rid of unit circle poles 43 | # [maxp,maxind] = max(abs(p)); 44 | # if isempty(p) % pure oscillator 45 | # N = periods; 46 | # elseif isempty(ind) % no oscillation 47 | # N = mltplcty(p,maxind)*log10(tol)/log10(maxp) + delay; 48 | # else % some of both 49 | # N = max(periods, ... 50 | # mltplcty(p,maxind)*log10(tol)/log10(maxp) ) + delay; 51 | return 1 52 | 53 | # function m = mltplcty( p, ind, tol) 54 | # %MLTPLCTY Multiplicity of a pole 55 | # % MLTPLCTY(P,IND,TOL) finds the multiplicity of P(IND) in the vector P 56 | # % with a tolerance of TOL. TOL defaults to .001. 57 | # 58 | # if nargin<3 59 | # tol = .001; 60 | # end 61 | # 62 | # [mults,indx]=mpoles(p,tol); 63 | # 64 | # m = mults(indx(ind)); 65 | # for i=indx(ind)+1:length(mults) 66 | # if mults(i)>m 67 | # m = m + 1; 68 | # else 69 | # break; 70 | # end 71 | # end 72 | -------------------------------------------------------------------------------- /src/arcov_matlab_vs_python.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Jan 22 22:26 2014 5 | 6 | @author: Sammy Pfeiffer 7 | @email: sammypfeiffer@gmail.com 8 | 9 | Test our python arcov vs the MatlabTM arcov 10 | 11 | MATLAB testing code from: 12 | http://www.music.mcgill.ca/~gary/307/matlab/predict.m 13 | """ 14 | from matlabpipe import MatlabPipe 15 | import numpy as np 16 | from arcov import arcov 17 | 18 | OKGREEN = '\033[92m' 19 | FAIL = '\033[91m' 20 | ENDC = '\033[0m' 21 | 22 | if __name__ == '__main__': 23 | matlab = MatlabPipe(matlab_version='2013a') 24 | matlab.open() 25 | 26 | cmd = """% Signal parameters. 27 | fs = 11025; 28 | T = 1/fs; 29 | N = 40000; % signal length 30 | t60 = [1.0 0.8 0.6 0.7 0.7]; % T60 decay constants 31 | tau = -t60/log(0.001); % 1/e decay constants 32 | f = [220 660 1100 4000 6000]; % sinusoid frequencies (Hz) 33 | phi = [pi/4 pi/2 pi 0 0]; % sinusoid phase offsets 34 | p = length(f); % number of resonances 35 | p = 3; 36 | 37 | t = [0:N]*T; % time vector 38 | x = 0; % initialize our input signal 39 | for n = 1:p, 40 | x = x + exp(-t/tau(n)).*sin(2*pi*f(n)*t+phi(n)); 41 | end 42 | x = 0.99*x/max(abs(x)); 43 | 44 | % Do linear prediction using covariance method. 45 | [a e] = arcov(x, 2*p);""" 46 | out = matlab.eval(cmd) 47 | # Get matlab inputs 48 | matlab_x = matlab.get('x') 49 | matlab_p = matlab.get('p') 50 | # Get matlab output of arcov 51 | matlab_a = matlab.get('a') 52 | matlab_e = matlab.get('e') 53 | 54 | 55 | # Use same inputs on python arcov 56 | [py_a, py_e] = arcov(matlab_x, 2*matlab_p) 57 | 58 | # Check if we get the same result 59 | print "\nMatlab a vs Python a" 60 | if np.allclose(matlab_a, py_a): # see if they are equal with relative tolerance=1e-05 and abs tol=1e-08 61 | print OKGREEN + "Coincident results!" + ENDC 62 | else: 63 | print FAIL +"Different results..." + ENDC 64 | print matlab_a 65 | print py_a 66 | 67 | 68 | print "\nMatlab e vs Python e" 69 | if np.allclose(matlab_e, py_e): # see if they are equal with relative tolerance=1e-05 and abs tol=1e-08 70 | print OKGREEN + "Coincident results!" + ENDC 71 | else: 72 | print FAIL +"Different results..." + ENDC 73 | print matlab_e 74 | print py_e 75 | -------------------------------------------------------------------------------- /src/armcov_matlab_vs_python.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Jan 22 22:26 2014 5 | 6 | @author: Sammy Pfeiffer 7 | @email: sammypfeiffer@gmail.com 8 | 9 | Test our python armcov vs the MatlabTM armcov 10 | 11 | MATLAB testing code from: 12 | http://www.music.mcgill.ca/~gary/307/matlab/predict.m 13 | """ 14 | from matlabpipe import MatlabPipe 15 | import numpy as np 16 | from armcov import armcov 17 | 18 | OKGREEN = '\033[92m' 19 | FAIL = '\033[91m' 20 | ENDC = '\033[0m' 21 | 22 | if __name__ == '__main__': 23 | matlab = MatlabPipe(matlab_version='2013a') 24 | matlab.open() 25 | 26 | cmd = """% Signal parameters. 27 | fs = 11025; 28 | T = 1/fs; 29 | N = 40000; % signal length 30 | t60 = [1.0 0.8 0.6 0.7 0.7]; % T60 decay constants 31 | tau = -t60/log(0.001); % 1/e decay constants 32 | f = [220 660 1100 4000 6000]; % sinusoid frequencies (Hz) 33 | phi = [pi/4 pi/2 pi 0 0]; % sinusoid phase offsets 34 | p = length(f); % number of resonances 35 | p = 3; 36 | 37 | t = [0:N]*T; % time vector 38 | x = 0; % initialize our input signal 39 | for n = 1:p, 40 | x = x + exp(-t/tau(n)).*sin(2*pi*f(n)*t+phi(n)); 41 | end 42 | x = 0.99*x/max(abs(x)); 43 | 44 | % Do linear prediction using covariance method. 45 | [a e] = armcov(x, 2*p);""" 46 | out = matlab.eval(cmd) 47 | # Get matlab inputs 48 | matlab_x = matlab.get('x') 49 | matlab_p = matlab.get('p') 50 | # Get matlab output of armcov 51 | matlab_a = matlab.get('a') 52 | matlab_e = matlab.get('e') 53 | 54 | 55 | # Use same inputs on python armcov 56 | [py_a, py_e] = armcov(matlab_x, 2*matlab_p) 57 | 58 | # Check if we get the same result 59 | print "\nMatlab a vs Python a" 60 | if np.allclose(matlab_a, py_a): # see if they are equal with relative tolerance=1e-05 and abs tol=1e-08 61 | print OKGREEN + "Coincident results!" + ENDC 62 | else: 63 | print FAIL +"Different results..." + ENDC 64 | print matlab_a 65 | print py_a 66 | 67 | 68 | print "\nMatlab e vs Python e" 69 | if np.allclose(matlab_e, py_e): # see if they are equal with relative tolerance=1e-05 and abs tol=1e-08 70 | print OKGREEN + "Coincident results!" + ENDC 71 | else: 72 | print FAIL +"Different results..." + ENDC 73 | print matlab_e 74 | print py_e 75 | -------------------------------------------------------------------------------- /src/invfreqs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Jan 22 23:56 2014 5 | 6 | I'm not really the author, but... 7 | @author: Sammy Pfeiffer 8 | @email: sammypfeiffer@gmail.com 9 | 10 | File found at: 11 | http://projects.scipy.org/scipy/attachment/ticket/393/invfreq.py 12 | 13 | Cleaned up a bit, removed unused imports. 14 | """ 15 | 16 | 17 | import numpy 18 | from numpy import atleast_1d, real 19 | from scipy.linalg import solve 20 | 21 | 22 | def invfreqs(g, worN, nB, nA, wf=None, nk=0): 23 | """Compute frequency response of a digital filter. 24 | 25 | Description: 26 | 27 | Computes the numerator (b) and denominator (a) of a digital filter compute 28 | its frequency response, given a frequency response at frequencies given in worN. 29 | 30 | nB nB-1 nk 31 | B(s) (b[0]s + b[1]s + .... + b[nB-1]s + b[nB])s 32 | H(s) = ---- = ----------------------------------------------- 33 | nA nA-1 34 | A(s) a[0]s + a[1]s + .... + a[nA-1]s+a[nA] 35 | 36 | with a[0]=1. 37 | 38 | Coefficients are determined by minimizing sum(wf |B-HA|**2). 39 | If opt is not None, minimization of sum(wf |H-B/A|**2) is done in at most 40 | MaxIter iterations until norm of gradient being less than Tol, 41 | with A constrained to be stable. 42 | 43 | Inputs: 44 | 45 | worN -- The frequencies at which h was computed. 46 | h -- The frequency response. 47 | 48 | Outputs: (w,h) 49 | 50 | b, a --- the numerator and denominator of a linear filter. 51 | """ 52 | g = atleast_1d(g) 53 | worN = atleast_1d(worN) 54 | if wf==None: 55 | wf = numpy.ones_like(worN) 56 | if len(g)!=len(worN) or len(worN)!=len(wf): 57 | raise ValueError, "The lengths of g, worN and wf must coincide." 58 | if numpy.any(worN<0): 59 | raise ValueError, "worN has negative values." 60 | s = 1j*worN 61 | 62 | # Constraining B(s) with nk trailing zeros 63 | nm = numpy.maximum(nA, nB+nk) 64 | mD = numpy.vander(1j*worN, nm+1) 65 | mH = numpy.mat(numpy.diag(g)) 66 | mM = numpy.mat(numpy.hstack(( mH*numpy.mat(mD[:,-nA:]),\ 67 | -numpy.mat(mD[:,-nk-nB-1:][:,:nB+1])))) 68 | mW = numpy.mat(numpy.diag(wf)) 69 | Y = solve(real(mM.H*mW*mM), -real(mM.H*mW*mH*numpy.mat(mD)[:,-nA-1])) 70 | a = numpy.ones(nA+1) 71 | a[1:] = Y[:nA].flatten() 72 | b = numpy.zeros(nB+nk+1) 73 | b[:nB+1] = Y[nA:].flatten() 74 | 75 | return b,a -------------------------------------------------------------------------------- /src/arcov.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Jan 22 20:38 2014 5 | 6 | @author: Sammy Pfeiffer 7 | @email: sammypfeiffer@gmail.com 8 | This file pretends to imitate the behaviour of the MATLAB function arcov 9 | 10 | Using spectrum implementation: 11 | http://thomas-cokelaer.info/software/spectrum/html/user/ref_psd_other.html#spectrum.covar.arcovar 12 | """ 13 | import numpy as np 14 | import spectrum 15 | 16 | def arcov(x, p): 17 | """From MATLAB: 18 | % A = ARCOV(X,ORDER) returns the polynomial A corresponding to the AR 19 | % parametric signal model estimate of vector X using the Covariance method. 20 | % ORDER is the model order of the AR system. 21 | % 22 | % [A,E] = ARCOV(...) returns the variance estimate E of the white noise 23 | % input to the AR model. 24 | 25 | Using from spectrum: 26 | def arcovar(x, order): 27 | Simple and fast implementation of the covariance AR estimate 28 | 29 | :param array X: Array of complex data samples 30 | :param int oder: Order of linear prediction model 31 | 32 | :return: 33 | * a - Array of complex forward linear prediction coefficients 34 | * e - error 35 | """ 36 | [A, E] = spectrum.covar.arcovar(x,p) 37 | A = np.hstack((1,A)) # MATLAB gives back initial value 1, so we do the same 38 | return A, E 39 | 40 | # Local Variables: a, msgobj, p, msg, x, e 41 | # Function calls: nargchk, arcov, nargin, isempty, error, arparest 42 | #%ARCOV AR parameter estimation via covariance method. 43 | #% A = ARCOV(X,ORDER) returns the polynomial A corresponding to the AR 44 | #% parametric signal model estimate of vector X using the Covariance method. 45 | #% ORDER is the model order of the AR system. 46 | #% 47 | #% [A,E] = ARCOV(...) returns the variance estimate E of the white noise 48 | #% input to the AR model. 49 | #% 50 | #% See also PCOV, ARMCOV, ARBURG, ARYULE, LPC, PRONY. 51 | #% Ref: S. Kay, MODERN SPECTRAL ESTIMATION, 52 | #% Prentice-Hall, 1988, Chapter 7 53 | #% P. Stoica and R. Moses, INTRODUCTION TO SPECTRAL ANALYSIS, 54 | #% Prentice-Hall, 1997, Chapter 3 55 | #% Author(s): R. Losada and P. Pacheco 56 | #% Copyright 1988-2002 The MathWorks, Inc. 57 | #% $Revision: 1.13.4.3 $ $Date: 2011/05/13 18:06:51 $ 58 | #matcompat.error(nargchk(2., 2., nargin, 'struct')) 59 | # [a, e, msg, msgobj] = arparest(x, p, 'covariance') 60 | # if not isempty(msg): 61 | # matcompat.error(msgobj) 62 | # 63 | # 64 | # #% [EOF] - arcov.m 65 | # return [a, e] -------------------------------------------------------------------------------- /matlab_test_files/stmcb.m: -------------------------------------------------------------------------------- 1 | function [b,a] = stmcb( x, u_in, q, p, niter, a_in ) 2 | %STMCB Compute linear model via Steiglitz-McBride iteration 3 | % [B,A] = stmcb(H,NB,NA) finds the coefficients of the system 4 | % B(z)/A(z) with approximate impulse response H, NA poles and 5 | % NB zeros. 6 | % 7 | % [B,A] = stmcb(H,NB,NA,N) uses N iterations. N defaults to 5. 8 | % 9 | % [B,A] = stmcb(H,NB,NA,N,Ai) uses the vector Ai as the initial 10 | % guess at the denominator coefficients. If you don't specify Ai, 11 | % STMCB uses [B,Ai] = PRONY(H,0,NA) as the initial conditions. 12 | % 13 | % [B,A] = STMCB(Y,X,NB,NA,N,Ai) finds the system coefficients B and 14 | % A of the system which, given X as input, has Y as output. N and Ai 15 | % are again optional with default values of N = 5, [B,Ai] = PRONY(Y,0,NA). 16 | % Y and X must be the same length. 17 | % 18 | % % Example: 19 | % % Approximate the impulse response of a Butterworth filter with a 20 | % % system of lower order. 21 | % 22 | % [b,a] = butter(6,0.2); % Butterworth filter design 23 | % h = filter(b,a,[1 zeros(1,100)]); % Filter data using above filter 24 | % freqz(b,a,128) % Frequency response 25 | % [bb,aa] = stmcb(h,4,4); 26 | % figure; freqz(bb,aa,128) 27 | % 28 | % See also PRONY, LEVINSON, LPC, ARYULE. 29 | 30 | % Author(s): Jim McClellan, 2-89 31 | % T. Krauss, 4-22-93, new help and options 32 | % Copyright 1988-2004 The MathWorks, Inc. 33 | % $Revision: 1.8.4.6 $ $Date: 2012/10/29 19:32:10 $ 34 | 35 | error(nargchk(3,6,nargin,'struct')) 36 | 37 | if length(u_in) == 1, 38 | if nargin == 3, 39 | niter = 5; p = q; q = u_in; 40 | a_in = prony(x,0,p); 41 | elseif nargin == 4, 42 | niter = p; p = q; q = u_in; 43 | a_in = prony(x,0,p); 44 | elseif nargin == 5, 45 | a_in = niter; niter = p; p = q; q = u_in; 46 | end 47 | u_in = zeros(size(x)); 48 | u_in(1) = 1; % make a unit impulse whose length is same as x 49 | else 50 | if length(u_in)~=length(x), 51 | error(message('signal:stmcb:InvalidDimensions')) 52 | end 53 | if nargin < 6 54 | [b,a_in] = prony(x,0,p); 55 | end 56 | if nargin < 5 57 | niter = 5; 58 | end 59 | end 60 | 61 | a = a_in; 62 | N = length(x); 63 | for i=1:niter 64 | u = filter( 1, a, x ); 65 | v = filter( 1, a, u_in ); 66 | C1 = convmtx(u(:),p+1); 67 | C2 = convmtx(v(:),q+1); 68 | T = [ -C1(1:N,:) C2(1:N,:) ]; 69 | c = T(:,2:p+q+2)\(-T(:,1)); % move 1st column to RHS and do least-squares 70 | a = [1; c(1:p)]; % denominator coefficients 71 | b = c(p+1:p+q+1); % numerator coefficients 72 | end 73 | a=a.'; 74 | b=b.'; 75 | 76 | -------------------------------------------------------------------------------- /src/by_hand_code/kalman.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ Computes the discrete Kalman filter """ 3 | from __future__ import division, print_function 4 | 5 | __author__ = 'Richard Lindsley' 6 | import numpy as np 7 | 8 | class Kalman(): 9 | def __init__(self, A, C, Qw, Qv, x00, P00): 10 | """ Initializes the discrete Kalman filter 11 | 12 | A: A(n-1) in x(n) = A(n-1)x(n-1) + w(n). A matrix, generally. 13 | C: C(n) in y(n) = C(n)x(n) + v(n). A matrix, generally. 14 | Qw: Autocorrelation matrix of w(n) 15 | Qv: Autocorrelation matrix of v(n) 16 | x00: Initial condition for x_hat(0|0) 17 | P00: Initial condition for P(0|0) 18 | 19 | Note that these values are stored as NumPy matrices to simplify the 20 | code below (due to multiple matrix multiplies needed) 21 | 22 | """ 23 | self._A = np.matrix(A) 24 | self._C = np.matrix(C) 25 | self._Qw = np.matrix(Qw) 26 | self._Qv = np.matrix(Qv) 27 | self._x00 = np.matrix(x00) 28 | self._P00 = P00 29 | 30 | self._n = 1 # time index 31 | self._x_n1_n1 = self._x00 # x_hat(n-1|n-1), initialized to x_hat(0|0) 32 | self._P_n1_n1 = self._P00 # P(n-1|n-1), initialized to P(0|0) 33 | 34 | # Computed later 35 | self._x_n_n1 = None # x_hat(n|n-1) 36 | self._x_n_n = None # x_hat(n|n) 37 | self._P_n_n1 = None # P(n|n-1) 38 | self._P_n_n = None # P(n|n) 39 | self._K = None # K(n), the Kalman gain 40 | 41 | def predict(self): 42 | """ Predict x(n|n-1) """ 43 | self._x_n_n1 = self._A * self._x_n1_n1 44 | self._P_n_n1 = self._A * self._P_n1_n1 * self._A.H + self._Qw 45 | self._K = self._P_n_n1 * self._C.H * (self._C * self._P_n_n1 * 46 | self._C.H + self._Qv).getI() 47 | return self._x_n_n1 48 | 49 | def update(self, y): 50 | """ Update x(n|n) with y(n) """ 51 | self._x_n_n = self._x_n_n1 + self._K * (y - self._C * self._x_n_n1) 52 | i = np.eye(self._P_n_n1.shape[0]) 53 | self._P_n_n = (i - self._K * self._C) * self._P_n_n1 54 | return self._x_n_n 55 | 56 | def timestep(self): 57 | """ Increment n and set variables accordingly """ 58 | self._n += 1 59 | self._x_n1_n1 = self._x_n_n 60 | self._P_n1_n1 = self._P_n_n 61 | 62 | def print_status(self): 63 | #print('n={} P(n|n-1)={:0.4} K(n)={:0.4} P(n|n)={:0.4}'.format(self._n, 64 | print('----------------') 65 | print(' n={}'.format(self._n)) 66 | print(' x(n|n)=\n{}'.format(self._x_n_n)) 67 | print(' P(n|n-1)=\n{}'.format(self._P_n_n1)) 68 | print(' K(n)=\n{}'.format(self._K)) 69 | print(' P(n|n)=\n{}'.format(self._P_n_n)) 70 | -------------------------------------------------------------------------------- /src/by_hand_code/convmtx.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ This file is a Python translation of the MATLAB file convm.m 3 | 4 | Python version by RDL 10 Jan 2012 5 | Copyright notice from convm.m: 6 | copyright 1996, by M.H. Hayes. For use with the book 7 | "Statistical Digital Signal Processing and Modeling" 8 | (John Wiley & Sons, 1996). 9 | """ 10 | 11 | import numpy as np 12 | 13 | def convmtx(v, n): 14 | """Generates a convolution matrix 15 | 16 | Usage: X = convm(v,n) 17 | Given a vector v of length N, an N+n-1 by n convolution matrix is 18 | generated of the following form: 19 | | v(0) 0 0 ... 0 | 20 | | v(1) v(0) 0 ... 0 | 21 | | v(2) v(1) v(0) ... 0 | 22 | X = | . . . . | 23 | | . . . . | 24 | | . . . . | 25 | | v(N) v(N-1) v(N-2) ... v(N-n+1) | 26 | | 0 v(N) v(N-1) ... v(N-n+2) | 27 | | . . . . | 28 | | . . . . | 29 | | 0 0 0 ... v(N) | 30 | And then it's trasposed to fit the MATLAB return value. 31 | That is, v is assumed to be causal, and zero-valued after N. 32 | 33 | """ 34 | N = len(v) + 2*n - 2 35 | xpad = np.concatenate([np.zeros(n-1), v[:], np.zeros(n-1)]) 36 | X = np.zeros((len(v)+n-1, n)) 37 | # Construct X column by column 38 | for i in xrange(n): 39 | X[:,i] = xpad[n-i-1:N-i] 40 | 41 | return X.transpose() 42 | 43 | def main(): 44 | """Just a test""" 45 | h = [1,2,3,2,1] 46 | X = convmtx(h,7) 47 | print(X) 48 | 49 | ## MATLAB OUTPUT: 50 | # >> h = [1 2 3 2 1]; 51 | # >> convmtx(h,7) 52 | # 53 | # ans = 54 | # 55 | # 1 2 3 2 1 0 0 0 0 0 0 56 | # 0 1 2 3 2 1 0 0 0 0 0 57 | # 0 0 1 2 3 2 1 0 0 0 0 58 | # 0 0 0 1 2 3 2 1 0 0 0 59 | # 0 0 0 0 1 2 3 2 1 0 0 60 | # 0 0 0 0 0 1 2 3 2 1 0 61 | # 0 0 0 0 0 0 1 2 3 2 1 62 | ## PYTHON OUTPUT: 63 | # array([[ 1., 2., 3., 2., 1., 0., 0., 0., 0., 0., 0.], 64 | # [ 0., 1., 2., 3., 2., 1., 0., 0., 0., 0., 0.], 65 | # [ 0., 0., 1., 2., 3., 2., 1., 0., 0., 0., 0.], 66 | # [ 0., 0., 0., 1., 2., 3., 2., 1., 0., 0., 0.], 67 | # [ 0., 0., 0., 0., 1., 2., 3., 2., 1., 0., 0.], 68 | 69 | 70 | 71 | if __name__ == '__main__': 72 | main() 73 | 74 | -------------------------------------------------------------------------------- /src/armcov.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Jan 22 20:38 2014 5 | 6 | @author: Sammy Pfeiffer 7 | @email: sammypfeiffer@gmail.com 8 | This file pretends to imitate the behaviour of the MATLAB function armcov 9 | 10 | Using spectrum implementation: 11 | http://thomas-cokelaer.info/software/spectrum/html/user/ref_psd_other.html 12 | search for modcovar (can't direct link it) 13 | """ 14 | import numpy as np 15 | import spectrum 16 | 17 | def armcov(x, p): 18 | """From MATLAB: 19 | % A = ARMCOV(X,ORDER) returns the polynomial A corresponding to the AR 20 | % parametric signal model estimate of vector X using the Modified Covariance 21 | % method. ORDER is the model order of the AR system. 22 | % 23 | % [A,E] = ARMCOV(...) returns the variance estimate E of the white noise 24 | % input to the AR model. 25 | 26 | Using from spectrum modcovar and modcovar_marple: 27 | Check http://thomas-cokelaer.info/software/spectrum/html/user/ref_psd_other.html#spectrum.modcovar.modcovar 28 | """ 29 | [E, A] = spectrum.modcovar(x, int(p)) # We compute this one because gives back same number of elements in E 30 | number_of_elements = len(E) 31 | [E, A, ISTAT] = spectrum.modcovar_marple(x, int(p)) # works slower but is more accurate with the error than modcovar 32 | E = E[:number_of_elements] 33 | E = np.hstack((1, E)) 34 | 35 | return E, A 36 | 37 | ### ORIGINAL IMPLEMENTATION 38 | # Local Variables: a, msgobj, p, msg, x, e 39 | # Function calls: nargchk, nargin, isempty, error, arparest, armcov 40 | #%ARMCOV AR parameter estimation via modified covariance method. 41 | #% A = ARMCOV(X,ORDER) returns the polynomial A corresponding to the AR 42 | #% parametric signal model estimate of vector X using the Modified Covariance 43 | #% method. ORDER is the model order of the AR system. 44 | #% 45 | #% [A,E] = ARMCOV(...) returns the variance estimate E of the white noise 46 | #% input to the AR model. 47 | #% 48 | #% See also PMCOV, ARCOV, ARBURG, ARYULE, LPC, PRONY. 49 | #% References: 50 | #% [1] S. Lawrence Marple, DIGITAL SPECTRAL ANALYSIS WITH APPLICATIONS, 51 | #% Prentice-Hall, 1987, Chapter 8 52 | #% [2] Steven M. Kay, MODERN SPECTRAL ESTIMATION THEORY & APPLICATION, 53 | #% Prentice-Hall, 1988, Chapter 7 54 | #% Author(s): R. Losada and P. Pacheco 55 | #% Copyright 1988-2002 The MathWorks, Inc. 56 | #% $Revision: 1.13.4.3 $ $Date: 2011/05/13 18:06:53 $ 57 | # matcompat.error(nargchk(2., 2., nargin, 'struct')) 58 | # [a, e, msg, msgobj] = arparest(x, p, 'modified') 59 | # if not isempty(msg): 60 | # matcompat.error(msgobj) 61 | # 62 | # 63 | # #% [EOF] - armcov.m 64 | # return [a, e] -------------------------------------------------------------------------------- /matlab_test_files/prony_test.m: -------------------------------------------------------------------------------- 1 | function [b,a] = prony_test(h, nb ,na) 2 | %PRONY Prony's method for time-domain IIR filter design. 3 | % [B,A] = PRONY(H, NB, NA) finds a filter with numerator order 4 | % NB, denominator order NA, and having the impulse response in 5 | % vector H. The IIR filter coefficients are returned in 6 | % length NB+1 and NA+1 row vectors B and A, ordered in 7 | % descending powers of Z. H may be real or complex. 8 | % 9 | % If the largest order specified is greater than the length of H, 10 | % H is padded with zeros. 11 | % 12 | % % Example: 13 | % % Fit an IIR model to an impulse response of a lowpass filter. 14 | % 15 | % [b,a] = butter(4,0.2); 16 | % impulseResp = impz(b,a); % obtain impulse response 17 | % denOrder=4; numOrder=4; % system function of order 4 18 | % [Num,Den]=prony(impulseResp,numOrder,denOrder); 19 | % subplot(211); % impulse response and input 20 | % stem(impz(Num,Den,length(impulseResp))); 21 | % title('Impulse Response with Prony Design'); 22 | % subplot(212); 23 | % stem(impulseResp); title('Input Impulse Response'); 24 | % 25 | % See also STMCB, LPC, BUTTER, CHEBY1, CHEBY2, ELLIP, INVFREQZ. 26 | 27 | % Author(s): L. Shure, 5-17-88 28 | % L. Shure, 12-17-90, revised 29 | % Copyright 1988-2012 The MathWorks, Inc. 30 | % $Revision: 1.7.4.1.2.1 $ $Date: 2013/01/02 17:47:48 $ 31 | 32 | % References: 33 | % [1] T.W. Parks and C.S. Burrus, Digital Filter Design, 34 | % John Wiley and Sons, 1987, p226. 35 | 36 | K = length(h) - 1; 37 | M = nb; N = na; 38 | display('K M N') 39 | K 40 | M 41 | N 42 | if K <= max(M,N) % zero-pad input if necessary 43 | K = max(M,N)+1; 44 | h(K+1) = 0; 45 | end 46 | c = h(1); 47 | if c==0 % avoid divide by zero 48 | c=1; 49 | end 50 | display('this is the second part of toeplitz') 51 | [1 zeros(1,K)] 52 | H = toeplitz(h/c,[1 zeros(1,K)]); 53 | display('toeplitz is') 54 | H 55 | % K+1 by N+1 56 | if (K > N) 57 | % display('H before doing this thing') 58 | % H 59 | H(:,(N+2):(K+1)) = []; % 43*43 matrix in my example and we are getting rid here of the columns... 60 | % K=43 M=4 N=4; H(all_rows, 4+2:43+1) 61 | % display('H after doing this [] thing') 62 | % H 63 | % error('exiting') 64 | end 65 | % Partition H matrix 66 | H1 = H(1:(M+1),:); % M+1 by N+1 67 | display('H1 is') 68 | H1 69 | 70 | h1 = H((M+2):(K+1),1); % K-M by 1 71 | % display('h1 is') 72 | % h1 73 | 74 | H2 = H((M+2):(K+1),2:(N+1)); % K-M by N 75 | % display('H2 is') 76 | % H2 77 | size(H2) 78 | display('h1 is') 79 | h1 80 | size(h1) 81 | display('sol -H2\h1') 82 | sol = -H2\h1 83 | % display('other way') % same result 84 | % mldivide(-H2,h1) 85 | a = [1; -H2\h1].'; 86 | b = c*a*H1.'; 87 | display('c*a') 88 | c*a 89 | display('c*a*H1') 90 | c*a*H1.' -------------------------------------------------------------------------------- /src/trashbin/system_example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sun Nov 17 12:30:46 2013 5 | 6 | @author: Sammy Pfeiffer 7 | """ 8 | from numpy import allclose # Grab all of the NumPy functions 9 | import numpy as np 10 | from matplotlib.pyplot import plot, show # Grab MATLAB plotting functions 11 | from control.matlab import tf, c2d, step # MATLAB-like functions 12 | #from scipy.signal import cont2discrete as c2d 13 | #from scipy.signal import step 14 | from stmcb import stmcb 15 | 16 | 17 | # MATLAB: 18 | # syst_fake=tf([1],[1 2 3]) # from matlab to python, commas must be used to separate elements 19 | # >> syst_fake 20 | # syst_fake = 21 | # 22 | # 1 23 | # ------------- 24 | # s^2 + 2 s + 3 25 | # 26 | # Continuous-time transfer function. 27 | 28 | syst_fake = tf([1],[1, 2, 3]) 29 | print syst_fake 30 | # Python: 31 | # 1 32 | # ------------- 33 | # s^2 + 2 s + 3 34 | 35 | 36 | # MATLAB: 37 | # zero order hold by default 38 | # syst_fake_dis=c2d(syst_fake,0.01) 39 | # syst_fake_dis = 40 | # 41 | # 4.967e-05 z + 4.934e-05 42 | # ----------------------- 43 | # z^2 - 1.98 z + 0.9802 44 | # 45 | # Sample time: 0.01 seconds 46 | # Discrete-time transfer function. 47 | 48 | #Test if we generated a system with the same behaviour: 49 | # MATLAB: 50 | # [output, t] = step(syst_fake) 51 | # plot(t, output) 52 | # Python 53 | # output, t = step([syst_fake.num[0][0][0], syst_fake.den[0][0]]) 54 | # plot(output, t) # MATLAB wants the inverse order to plot 55 | # show() 56 | 57 | 58 | syst_fake_dis = c2d(syst_fake, 0.01, method='zoh') 59 | print syst_fake_dis 60 | # OLD scipy.signal.cont2discrete way! 61 | #syst_fake_dis = c2d([syst_fake.num[0][0][0], syst_fake.den[0][0]], 0.01) 62 | #print_c2d_matlablike(syst_fake_dis) 63 | 64 | # Python: 65 | # zero order hold by default 66 | # 4.96670866519e-05 z 4.93370716897e-05 67 | # ----------------------- 68 | # z^2 1.0 z^2 -1.97990166083 z 0.980198673307 69 | # 70 | # Sample time: 0.01 seconds 71 | # Discrete-time transfer function. 72 | 73 | # MATLAB: 74 | # [output,t]=step(syst_fake_dis) 75 | ### OLD scipy.signal.step way! 76 | ###output, t = step(syst_fake_dis[0][0], syst_fake_dis[1])# ,T=200) # MATLAB calculates the T size automatically based on black magic different than python one, see [MATLAB]/toolbox/shared/controllib/engine/@DynamicSystem/step.m: 77 | output, t = step(syst_fake_dis) 78 | # MATLAB: 79 | # plot(output) 80 | plot(output[0]) 81 | show() 82 | 83 | # out_len = len(output) 84 | out_len = len(output[0]) 85 | print "out_len is:" 86 | print out_len 87 | print "output is:" 88 | print output[0] 89 | # input=1:650; 90 | # input(:)=1; 91 | input_ = np.ones(out_len) 92 | # [num,den]=stmcb(output,input,0,2) 93 | [num,den]=stmcb(output[0],input_,0,2) 94 | # sys_model=tf(num,den,0.01) 95 | # step(sys_model) 96 | # hold on 97 | # step(syst_fake) -------------------------------------------------------------------------------- /src/by_hand_code/system_example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sun Nov 17 12:30:46 2013 5 | 6 | @author: Sammy Pfeiffer 7 | """ 8 | from numpy import allclose # Grab all of the NumPy functions 9 | import numpy as np 10 | from matplotlib.pyplot import plot, show # Grab MATLAB plotting functions 11 | from control.matlab import tf, c2d, step # MATLAB-like functions 12 | #from scipy.signal import cont2discrete as c2d 13 | #from scipy.signal import step 14 | from stmbc import stmcb 15 | 16 | 17 | # MATLAB: 18 | # syst_fake=tf([1],[1 2 3]) # from matlab to python, commas must be used to separate elements 19 | # >> syst_fake 20 | # syst_fake = 21 | # 22 | # 1 23 | # ------------- 24 | # s^2 + 2 s + 3 25 | # 26 | # Continuous-time transfer function. 27 | 28 | syst_fake = tf([1],[1, 2, 3]) 29 | print syst_fake 30 | # Python: 31 | # 1 32 | # ------------- 33 | # s^2 + 2 s + 3 34 | 35 | 36 | # MATLAB: 37 | # zero order hold by default 38 | # syst_fake_dis=c2d(syst_fake,0.01) 39 | # syst_fake_dis = 40 | # 41 | # 4.967e-05 z + 4.934e-05 42 | # ----------------------- 43 | # z^2 - 1.98 z + 0.9802 44 | # 45 | # Sample time: 0.01 seconds 46 | # Discrete-time transfer function. 47 | 48 | #Test if we generated a system with the same behaviour: 49 | # MATLAB: 50 | # [output, t] = step(syst_fake) 51 | # plot(t, output) 52 | # Python 53 | # output, t = step([syst_fake.num[0][0][0], syst_fake.den[0][0]]) 54 | # plot(output, t) # MATLAB wants the inverse order to plot 55 | # show() 56 | 57 | 58 | syst_fake_dis = c2d(syst_fake, 0.01, method='zoh') 59 | print syst_fake_dis 60 | # OLD scipy.signal.cont2discrete way! 61 | #syst_fake_dis = c2d([syst_fake.num[0][0][0], syst_fake.den[0][0]], 0.01) 62 | #print_c2d_matlablike(syst_fake_dis) 63 | 64 | # Python: 65 | # zero order hold by default 66 | # 4.96670866519e-05 z 4.93370716897e-05 67 | # ----------------------- 68 | # z^2 1.0 z^2 -1.97990166083 z 0.980198673307 69 | # 70 | # Sample time: 0.01 seconds 71 | # Discrete-time transfer function. 72 | 73 | # MATLAB: 74 | # [output,t]=step(syst_fake_dis) 75 | ### OLD scipy.signal.step way! 76 | ###output, t = step(syst_fake_dis[0][0], syst_fake_dis[1])# ,T=200) # MATLAB calculates the T size automatically based on black magic different than python one, see [MATLAB]/toolbox/shared/controllib/engine/@DynamicSystem/step.m: 77 | output, t = step(syst_fake_dis) 78 | # MATLAB: 79 | # plot(output) 80 | plot(output[0]) 81 | show() 82 | 83 | # out_len = len(output) 84 | out_len = len(output[0]) 85 | print "out_len is:" 86 | print out_len 87 | print "output is:" 88 | print output[0] 89 | # input=1:650; 90 | # input(:)=1; 91 | input_ = np.ones(out_len) 92 | # [num,den]=stmcb(output,input,0,2) 93 | [num,den]=stmcb(output[0],input_,0,2) 94 | # sys_model=tf(num,den,0.01) 95 | # step(sys_model) 96 | # hold on 97 | # step(syst_fake) -------------------------------------------------------------------------------- /matlab_test_files/prony_to_py.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | import scipy 4 | import matcompat 5 | 6 | # if available import pylab (from matlibplot) 7 | try: 8 | import matplotlib.pylab as plt 9 | except ImportError: 10 | pass 11 | 12 | def prony(h, nb, na): 13 | 14 | # Local Variables: a, c, b, h1, h, nb, H1, M, N, H2, H, na, H2_minus, K 15 | # Function calls: max, length, prony, zeros, toeplitz 16 | #%PRONY Prony's method for time-domain IIR filter design. 17 | #% [B,A] = PRONY(H, NB, NA) finds a filter with numerator order 18 | #% NB, denominator order NA, and having the impulse response in 19 | #% vector H. The IIR filter coefficients are returned in 20 | #% length NB+1 and NA+1 row vectors B and A, ordered in 21 | #% descending powers of Z. H may be real or complex. 22 | #% 23 | #% If the largest order specified is greater than the length of H, 24 | #% H is padded with zeros. 25 | #% 26 | #% % Example: 27 | #% % Fit an IIR model to an impulse response of a lowpass filter. 28 | #% 29 | #% [b,a] = butter(4,0.2); 30 | #% impulseResp = impz(b,a); % obtain impulse response 31 | #% denOrder=4; numOrder=4; % system function of order 4 32 | #% [Num,Den]=prony(impulseResp,numOrder,denOrder); 33 | #% subplot(211); % impulse response and input 34 | #% stem(impz(Num,Den,length(impulseResp))); 35 | #% title('Impulse Response with Prony Design'); 36 | #% subplot(212); 37 | #% stem(impulseResp); title('Input Impulse Response'); 38 | #% 39 | #% See also STMCB, LPC, BUTTER, CHEBY1, CHEBY2, ELLIP, INVFREQZ. 40 | #% Author(s): L. Shure, 47-88 41 | #% L. Shure, 117-90, revised 42 | #% Copyright 1988-2012 The MathWorks, Inc. 43 | #% $Revision: 1.7.4.1.2.1 $ $Date: 2013/01/02 17:47:48 $ 44 | #% References: 45 | #% [1] T.W. Parks and C.S. Burrus, Digital Filter Design, 46 | #% John Wiley and Sons, 1987, p226. 47 | K = length(h)-1. 48 | M = nb 49 | N = na 50 | if K<=matcompat.max(M, N): 51 | #% zero-pad input if necessary 52 | K = matcompat.max(M, N)+1. 53 | h[int((K+1.))-1] = 0. 54 | 55 | c = h[0] 56 | if c == 0.: 57 | #% avoid divide by zero 58 | c = 1. 59 | 60 | H = toeplitz(matdiv(h, c), np.array(np.hstack((1., np.zeros(1., K))))) 61 | #% K+1 by N+1 62 | if K > N: 63 | H[:,int(N+2.)-1:K+1.] = np.array([]) 64 | 65 | 66 | #% Partition H matrix 67 | H1 = H[0:M+1.,:] 68 | #% M+1 by N+1 69 | h1 = H[int(M+2.)-1:K+1.,0] 70 | #% K-M by 1 71 | H2 = H[int(M+2.)-1:K+1.,1:N+1.] 72 | #% K-M by N 73 | H2_minus = -H2 74 | a = np.array(np.vstack((np.hstack((1.)), np.hstack((linalg.solve(H2_minus, h1)))))).T 75 | b = np.dot(np.dot(c, a), H1.T) 76 | return [b, a] -------------------------------------------------------------------------------- /matlab_test_files/aryule_test.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | import scipy 4 | import matcompat 5 | 6 | # if available import pylab (from matlibplot) 7 | try: 8 | import matplotlib.pylab as plt 9 | except ImportError: 10 | pass 11 | 12 | def aryule(x, p): 13 | 14 | # Local Variables: a, e, k, nx, p, R, x, mx 15 | # Function calls: aryule, nargchk, min, issparse, nargin, length, isempty, error, levinson, message, xcorr, round, size 16 | #%ARYULE AR parameter estimation via Yule-Walker method. 17 | #% A = ARYULE(X,ORDER) returns the polynomial A corresponding to the AR 18 | #% parametric signal model estimate of vector X using the Yule-Walker 19 | #% (autocorrelation) method. ORDER is the model order of the AR system. 20 | #% This method solves the Yule-Walker equations by means of the Levinson- 21 | #% Durbin recursion. 22 | #% 23 | #% [A,E] = ARYULE(...) returns the final prediction error E (the variance 24 | #% estimate of the white noise input to the AR model). 25 | #% 26 | #% [A,E,K] = ARYULE(...) returns the vector K of reflection coefficients. 27 | #% 28 | #% % Example: 29 | #% % Estimate model order using decay of reflection coefficients. 30 | #% 31 | #% rng default; 32 | #% y=filter(1,[1 -0.75 0.5],0.2*randn(1024,1)); 33 | #% 34 | #% % Create AR(2) process 35 | #% [ar_coeffs,NoiseVariance,reflect_coeffs]=aryule(y,10); 36 | #% 37 | #% % Fit AR(10) model 38 | #% stem(reflect_coeffs); axis([-0.05 10.5 -1 1]); 39 | #% title('Reflection Coefficients by Lag'); xlabel('Lag'); 40 | #% ylabel('Reflection Coefficent'); 41 | #% 42 | #% See also PYULEAR, ARMCOV, ARBURG, ARCOV, LPC, PRONY. 43 | #% Ref: S. Orfanidis, OPTIMUM SIGNAL PROCESSING, 2nd Ed. 44 | #% Macmillan, 1988, Chapter 5 45 | #% M. Hayes, STATISTICAL DIGITAL SIGNAL PROCESSING AND MODELING, 46 | #% John Wiley & Sons, 1996, Chapter 8 47 | #% Author(s): R. Losada 48 | #% Copyright 1988-2004 The MathWorks, Inc. 49 | #% $Revision: 1.12.4.6 $ $Date: 2012/10/29 19:30:38 $ 50 | matcompat.error(nargchk(2., 2., nargin, 'struct')) 51 | #% Check the input data type. Single precision is not supported. 52 | #%try 53 | #% chkinputdatatype(x,p); 54 | #%catch ME 55 | #% throwAsCaller(ME); 56 | #%end 57 | [mx, nx] = matcompat.size(x) 58 | if isempty(x) or length(x)

1.: 59 | matcompat.error(message('signal:aryule:InvalidDimensions')) 60 | elif isempty(p) or not p == np.round(p): 61 | matcompat.error(message('signal:aryule:MustBeInteger')) 62 | 63 | 64 | if issparse(x): 65 | matcompat.error(message('signal:aryule:Sparse')) 66 | 67 | 68 | R = plt.xcorr(x, p, 'biased') 69 | [a, e, k] = levinson(R[int(p+1.)-1:], p) 70 | return [a, e, k] -------------------------------------------------------------------------------- /matlab_test_files/stmcb_to_py.m: -------------------------------------------------------------------------------- 1 | function [b,a] = stmcb( x, u_in, q, p, niter, a_in ) 2 | %STMCB Compute linear model via Steiglitz-McBride iteration 3 | % [B,A] = stmcb(H,NB,NA) finds the coefficients of the system 4 | % B(z)/A(z) with approximate impulse response H, NA poles and 5 | % NB zeros. 6 | % 7 | % [B,A] = stmcb(H,NB,NA,N) uses N iterations. N defaults to 5. 8 | % 9 | % [B,A] = stmcb(H,NB,NA,N,Ai) uses the vector Ai as the initial 10 | % guess at the denominator coefficients. If you don't specify Ai, 11 | % STMCB uses [B,Ai] = PRONY(H,0,NA) as the initial conditions. 12 | % 13 | % [B,A] = STMCB(Y,X,NB,NA,N,Ai) finds the system coefficients B and 14 | % A of the system which, given X as input, has Y as output. N and Ai 15 | % are again optional with default values of N = 5, [B,Ai] = PRONY(Y,0,NA). 16 | % Y and X must be the same length. 17 | % 18 | % % Example: 19 | % % Approximate the impulse response of a Butterworth filter with a 20 | % % system of lower order. 21 | % 22 | % [b,a] = butter(6,0.2); % Butterworth filter design 23 | % h = filter(b,a,[1 zeros(1,100)]); % Filter data using above filter 24 | % freqz(b,a,128) % Frequency response 25 | % [bb,aa] = stmcb(h,4,4); 26 | % figure; freqz(bb,aa,128) 27 | % 28 | % See also PRONY, LEVINSON, LPC, ARYULE. 29 | 30 | % Author(s): Jim McClellan, 2-89 31 | % T. Krauss, 4-22-93, new help and options 32 | % Copyright 1988-2004 The MathWorks, Inc. 33 | % $Revision: 1.8.4.6 $ $Date: 2012/10/29 19:32:10 $ 34 | 35 | error(nargchk(3,6,nargin,'struct')) 36 | 37 | if length(u_in) == 1, 38 | if nargin == 3, 39 | niter = 5; p = q; q = u_in; 40 | a_in = prony(x,0,p); 41 | elseif nargin == 4, 42 | niter = p; p = q; q = u_in; 43 | a_in = prony(x,0,p); 44 | elseif nargin == 5, 45 | a_in = niter; niter = p; p = q; q = u_in; 46 | end 47 | u_in = zeros(size(x)); 48 | u_in(1) = 1; % make a unit impulse whose length is same as x 49 | else 50 | if length(u_in)~=length(x), 51 | error(message('signal:stmcb:InvalidDimensions')) 52 | end 53 | if nargin < 6 54 | [b,a_in] = prony(x,0,p); 55 | end 56 | if nargin < 5 57 | niter = 5; 58 | end 59 | end 60 | 61 | a = a_in; 62 | N = length(x); 63 | for i=1:niter 64 | u = filter( 1, a, x ); 65 | v = filter( 1, a, u_in ); 66 | C1 = convmtx(u(:),p+1); 67 | C2 = convmtx(v(:),q+1); 68 | C1_minus = -C1; 69 | T_sub1 = C1_minus(1:N,:); 70 | T_sub2 = C2(1:N,:); 71 | T = [T_sub1 T_sub2]; 72 | %T = [ C1_minus(1:N,:) C2(1:N,:) ]; 73 | T_minus = -T; 74 | T_left = T(:,2:p+q+2); 75 | T_right = (T_minus(:,1)); 76 | c = T_left \ T_right; 77 | % c = T(:,2:p+q+2)\(T_minus(:,1)); % move 1st column to RHS and do least-squares 78 | a = [1; c(1:p)]; % denominator coefficients 79 | b = c(p+1:p+q+1); % numerator coefficients 80 | end 81 | a=a.'; 82 | b=b.'; 83 | 84 | -------------------------------------------------------------------------------- /matlab_test_files/arparest.m: -------------------------------------------------------------------------------- 1 | function [a,e,msg,msgobj] = arparest( x, p, method) 2 | %ARPAREST AR parameter estimation via a specified method. 3 | % A = ARPAREST(X,ORDER,METHOD) returns the polynomial A corresponding to 4 | % the AR parametric signal model estimate of vector X using the specified 5 | % METHOD. ORDER is the model order of the AR system. 6 | % 7 | % Supported methods are: 'covariance' and 'modified' although all of the 8 | % methods of CORRMTX will work. In particular if 'autocorrelation' is 9 | % used, the results should be the same as those of ARYULE (but slower). 10 | % 11 | % [A,E] = ARPAREST(...) returns the variance estimate E of the white noise 12 | % input to the AR model. 13 | 14 | % Ref: S. Kay, MODERN SPECTRAL ESTIMATION, 15 | % Prentice-Hall, 1988, Chapter 7 16 | % S. Marple, DIGITAL SPECTRAL ANALYSIS WITH APPLICATION, 17 | % Prentice-Hall, 1987, Chapter 8. 18 | % P. Stoica and R. Moses, INTRODUCTION TO SPECTRAL ANALYSIS, 19 | % Prentice-Hall, 1997, Chapter 3 20 | 21 | % Author(s): R. Losada and P. Pacheco 22 | % Copyright 1988-2004 The MathWorks, Inc. 23 | % $Revision: 1.5.4.3 $ $Date: 2011/05/13 18:13:56 $ 24 | 25 | error(nargchk(3,3,nargin,'struct')) 26 | [mx,nx] = size(x); 27 | 28 | % Initialize in case we return early 29 | a = []; e = []; 30 | 31 | % Assign msg in case there are no errors 32 | msg =''; 33 | msgobj = []; 34 | 35 | % Set up necessary but not sufficient conditions for the correlation 36 | % matrix to be nonsingular. From (Marple) 37 | switch method, 38 | case 'covariance', 39 | minlength_x = 2*p; 40 | case 'modified', 41 | minlength_x = 3*p/2; 42 | otherwise 43 | msgobj = message('signal:arparest:UnknMethod'); 44 | msg = getString(msgobj); 45 | return 46 | end 47 | 48 | % Do some data sanity testing 49 | if isempty(x) || length(x) < minlength_x || min(mx,nx) > 1, 50 | if strcmp(method, 'modified') 51 | msgobj = message('signal:arparest:TooSmallForModel','X','3/2'); 52 | msg = getString(msgobj); 53 | else 54 | msgobj = message('signal:arparest:TooSmallForModel','X','2'); 55 | msg = getString(msgobj); 56 | end 57 | return 58 | end 59 | if issparse(x), 60 | msgobj = message('signal:arparest:InputSignalCannotBeSparse'); 61 | msg = getString(msgobj); 62 | return 63 | end 64 | if isempty(p) || p ~= round(p), 65 | msgobj = message('signal:arparest:ModelOrderMustBeInteger'); 66 | msg = getString(msgobj); 67 | return 68 | end 69 | 70 | x = x(:); 71 | 72 | % Generate the appropriate data matrix 73 | XM = corrmtx(x,p,method); 74 | Xc = XM(:,2:end); 75 | X1 = XM(:,1); 76 | 77 | % Coefficients estimated via the covariance method 78 | a = [1; -Xc\X1]; 79 | 80 | % Estimate the input white noise variance 81 | Cz = X1'*Xc; 82 | e = X1'*X1 + Cz*a(2:end); 83 | 84 | % Ignore the possible imaginary part due to numerical errors and force 85 | % the variance estimate of the white noise to be positive 86 | e = abs(real(e)); 87 | 88 | a = a(:).'; % By convention all polynomials are row vectors 89 | 90 | % [EOF] arparest.m 91 | -------------------------------------------------------------------------------- /matlab_test_files/stmcb_test.m: -------------------------------------------------------------------------------- 1 | function [b,a] = stmcb_test( x, u_in, q, p, niter, a_in ) 2 | %STMCB Compute linear model via Steiglitz-McBride iteration 3 | % [B,A] = stmcb(H,NB,NA) finds the coefficients of the system 4 | % B(z)/A(z) with approximate impulse response H, NA poles and 5 | % NB zeros. 6 | % 7 | % [B,A] = stmcb(H,NB,NA,N) uses N iterations. N defaults to 5. 8 | % 9 | % [B,A] = stmcb(H,NB,NA,N,Ai) uses the vector Ai as the initial 10 | % guess at the denominator coefficients. If you don't specify Ai, 11 | % STMCB uses [B,Ai] = PRONY(H,0,NA) as the initial conditions. 12 | % 13 | % [B,A] = STMCB(Y,X,NB,NA,N,Ai) finds the system coefficients B and 14 | % A of the system which, given X as input, has Y as output. N and Ai 15 | % are again optional with default values of N = 5, [B,Ai] = PRONY(Y,0,NA). 16 | % Y and X must be the same length. 17 | % 18 | % % Example: 19 | % % Approximate the impulse response of a Butterworth filter with a 20 | % % system of lower order. 21 | % 22 | % [b,a] = butter(6,0.2); % Butterworth filter design 23 | % h = filter(b,a,[1 zeros(1,100)]); % Filter data using above filter 24 | % freqz(b,a,128) % Frequency response 25 | % [bb,aa] = stmcb(h,4,4); 26 | % figure; freqz(bb,aa,128) 27 | % 28 | % See also PRONY, LEVINSON, LPC, ARYULE. 29 | 30 | % Author(s): Jim McClellan, 2-89 31 | % T. Krauss, 4-22-93, new help and options 32 | % Copyright 1988-2004 The MathWorks, Inc. 33 | % $Revision: 1.8.4.6 $ $Date: 2012/10/29 19:32:10 $ 34 | 35 | error(nargchk(3,6,nargin,'struct')) 36 | 37 | if length(u_in) == 1, 38 | if nargin == 3, 39 | niter = 5; p = q; q = u_in; 40 | a_in = prony(x,0,p); 41 | elseif nargin == 4, 42 | niter = p; p = q; q = u_in; 43 | a_in = prony(x,0,p); 44 | elseif nargin == 5, 45 | a_in = niter; niter = p; p = q; q = u_in; 46 | end 47 | u_in = zeros(size(x)); 48 | u_in(1) = 1; % make a unit impulse whose length is same as x 49 | else 50 | if length(u_in)~=length(x), 51 | error(message('signal:stmcb:InvalidDimensions')) 52 | end 53 | if nargin < 6 54 | [b,a_in] = prony(x,0,p); 55 | disp('p is:') 56 | disp(p) 57 | disp('b is:') 58 | disp(b) 59 | disp('a_in is:') 60 | disp(a_in) 61 | end 62 | if nargin < 5 63 | niter = 5; 64 | end 65 | end 66 | 67 | a = a_in; 68 | N = length(x); 69 | for i=1:niter 70 | u = filter( 1, a, x ); 71 | %u 72 | v = filter( 1, a, u_in ); 73 | %v 74 | C1 = convmtx_test(u(:),p+1); 75 | C2 = convmtx_test(v(:),q+1); 76 | %T_left = -C1(1:N,:) 77 | %size(T_left) 78 | %T_right = C2(1:N,:) 79 | %size(T_right) 80 | T = [ -C1(1:N,:) C2(1:N,:) ]; 81 | %T 82 | %size(T) 83 | %error('stop here') 84 | c = T(:,2:p+q+2)\(-T(:,1)); % move 1st column to RHS and do least-squares 85 | c 86 | size(c) 87 | a = [1; c(1:p)]; % denominator coefficients 88 | a 89 | size(a) 90 | b = c(p+1:p+q+1); % numerator coefficients 91 | end 92 | a=a.'; 93 | b=b.'; 94 | 95 | -------------------------------------------------------------------------------- /src/by_hand_code/prony_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sun Jan 5 17:11:46 2014 5 | 6 | @author: Sammy Pfeiffer 7 | This file is a test for using prony python implementation versus MATLAB one. 8 | """ 9 | 10 | import numpy as np 11 | from prony import prony 12 | from prony_matlab import prony_matlab 13 | from scipy.signal import butter, impulse 14 | from impz import impz 15 | 16 | # % % Example: 17 | # % % Fit an IIR model to an impulse response of a lowpass filter. 18 | # % 19 | # % [b,a] = butter(4,0.2); 20 | b, a = butter(4, 0.2) 21 | # MATLAB output 22 | # Python output 23 | 24 | # b = 0.0048 0.0193 0.0289 0.0193 0.0048 25 | #[ 0.00482434 0.01929737 0.02894606 0.01929737 0.00482434] 26 | 27 | # a = 1.0000 -2.3695 2.3140 -1.0547 0.1874 28 | #[ 1. -2.36951301 2.31398841 -1.05466541 0.18737949] 29 | print b 30 | print a 31 | 32 | # % impulseResp = impz(b,a); % obtain impulse response 33 | # 0.00482434335771622 0.0307287177680857 0.0905946819548826 0.167944821844737 0.224641271344028 0.233457187867600 0.193512552162805 0.123765243571016 0.0496036031380585 -0.00850905187491667 -0.0406738350178057 -0.0475631979469677 -0.0368517338223919 -0.0185628385243508 -0.00125221912683403 0.0100331628527336 0.0139990059845164 0.0121118272327115 0.00712186446378598 0.00173298095479121 -0.00222279239538353 -0.00403535730812247 -0.00392509206552861 -0.00263181398008669 -0.000992945935699223 0.000353673136269240 0.00109549708726230 0.00122332129708734 0.000922772684652072 0.000444882357824948 3.79019631817530e-06 -0.000276480597968442 -0.000367601488225979 -0.000310628048735716 -0.000177716344133915 -3.82012617315314e-05 6.19874979750476e-05 0.000106051505667546 0.000100862919097785 6.61282460408185e-05 2.35297812645709e-05 -1.07611182300523e-05 -2.91027199865281e-05 34 | impulseResp = impz(b,a) 35 | print impulseResp 36 | # I used a couple of examples... matlab gave 43 as length we give 64 37 | # python [ 0.00482434 0.03072872 0.09059468 0.16794482 0.22464127] 38 | # matlab 0.00482434335771622 0.0307287177680857 0.0905946819548826 0.167944821844737 0.224641271344028 39 | 40 | # % denOrder=4; numOrder=4; % system function of order 4 41 | denOrder = 4 42 | numOrder = 4 43 | 44 | # % [Num,Den]=prony(impulseResp,numOrder,denOrder); 45 | #[Num,Den]=prony(impulseResp,numOrder,denOrder) 46 | [Num,Den]=prony_matlab(impulseResp,numOrder,denOrder) 47 | # MATLAB 48 | # Num =0.0048 0.0193 0.0289 0.0193 0.0048 49 | # Den =1.0000 -2.3695 2.3140 -1.0547 0.1874 50 | # Python 51 | # [ 0.00482434 0.01929737 0.02894606 0.01929737 0.00482434] 52 | # [ 1. -2.36951301 2.31398841 -1.05466541 0.18737949] 53 | 54 | print Num 55 | print Den 56 | 57 | # % subplot(211); % impulse response and input 58 | # % stem(impz(Num,Den,length(impulseResp))); 59 | # % title('Impulse Response with Prony Design'); 60 | # % subplot(212); 61 | # % stem(impulseResp); title('Input Impulse Response'); 62 | 63 | 64 | -------------------------------------------------------------------------------- /matlab_test_files/arparest_test.m: -------------------------------------------------------------------------------- 1 | function [a,e,msg,msgobj] = arparest( x, p, method) 2 | %ARPAREST AR parameter estimation via a specified method. 3 | % A = ARPAREST(X,ORDER,METHOD) returns the polynomial A corresponding to 4 | % the AR parametric signal model estimate of vector X using the specified 5 | % METHOD. ORDER is the model order of the AR system. 6 | % 7 | % Supported methods are: 'covariance' and 'modified' although all of the 8 | % methods of CORRMTX will work. In particular if 'autocorrelation' is 9 | % used, the results should be the same as those of ARYULE (but slower). 10 | % 11 | % [A,E] = ARPAREST(...) returns the variance estimate E of the white noise 12 | % input to the AR model. 13 | 14 | % Ref: S. Kay, MODERN SPECTRAL ESTIMATION, 15 | % Prentice-Hall, 1988, Chapter 7 16 | % S. Marple, DIGITAL SPECTRAL ANALYSIS WITH APPLICATION, 17 | % Prentice-Hall, 1987, Chapter 8. 18 | % P. Stoica and R. Moses, INTRODUCTION TO SPECTRAL ANALYSIS, 19 | % Prentice-Hall, 1997, Chapter 3 20 | 21 | % Author(s): R. Losada and P. Pacheco 22 | % Copyright 1988-2004 The MathWorks, Inc. 23 | % $Revision: 1.5.4.3 $ $Date: 2011/05/13 18:13:56 $ 24 | 25 | error(nargchk(3,3,nargin,'struct')) 26 | [mx,nx] = size(x); 27 | 28 | % Initialize in case we return early 29 | a = []; e = []; 30 | 31 | % Assign msg in case there are no errors 32 | msg =''; 33 | msgobj = []; 34 | 35 | % Set up necessary but not sufficient conditions for the correlation 36 | % matrix to be nonsingular. From (Marple) 37 | switch method, 38 | case 'covariance', 39 | minlength_x = 2*p; 40 | case 'modified', 41 | minlength_x = 3*p/2; 42 | otherwise 43 | msgobj = message('signal:arparest:UnknMethod'); 44 | msg = getString(msgobj); 45 | return 46 | end 47 | 48 | % Do some data sanity testing 49 | if isempty(x) || length(x) < minlength_x || min(mx,nx) > 1, 50 | if strcmp(method, 'modified') 51 | msgobj = message('signal:arparest:TooSmallForModel','X','3/2'); 52 | msg = getString(msgobj); 53 | else 54 | msgobj = message('signal:arparest:TooSmallForModel','X','2'); 55 | msg = getString(msgobj); 56 | end 57 | return 58 | end 59 | if issparse(x), 60 | msgobj = message('signal:arparest:InputSignalCannotBeSparse'); 61 | msg = getString(msgobj); 62 | return 63 | end 64 | if isempty(p) || p ~= round(p), 65 | msgobj = message('signal:arparest:ModelOrderMustBeInteger'); 66 | msg = getString(msgobj); 67 | return 68 | end 69 | 70 | x = x(:); 71 | 72 | % Generate the appropriate data matrix 73 | XM = corrmtx(x,p,method); 74 | Xc = XM(:,2:end); 75 | X1 = XM(:,1); 76 | 77 | % Coefficients estimated via the covariance method 78 | a_left = [1] 79 | Xc_minus = -Xc 80 | a_right = Xc_minus\X1 81 | a = [a_left; a_right] 82 | %a = [1; -Xc\X1]; 83 | 84 | % Estimate the input white noise variance 85 | Cz = X1'*Xc; 86 | e = X1'*X1 + Cz*a(2:end); 87 | 88 | % Ignore the possible imaginary part due to numerical errors and force 89 | % the variance estimate of the white noise to be positive 90 | e = abs(real(e)); 91 | 92 | a = a(:).'; % By convention all polynomials are row vectors 93 | 94 | % [EOF] arparest.m 95 | -------------------------------------------------------------------------------- /matlab_test_files/arburg.m: -------------------------------------------------------------------------------- 1 | function varargout = arburg( x, p) 2 | %ARBURG AR parameter estimation via Burg method. 3 | % A = ARBURG(X,ORDER) returns the polynomial A corresponding to the AR 4 | % parametric signal model estimate of vector X using Burg's method. 5 | % ORDER is the model order of the AR system. 6 | % 7 | % [A,E] = ARBURG(...) returns the final prediction error E (the variance 8 | % estimate of the white noise input to the AR model). 9 | % 10 | % [A,E,K] = ARBURG(...) returns the vector K of reflection 11 | % coefficients (parcor coefficients). 12 | % 13 | % % Example: 14 | % % Estimate input noise variance for AR(4) model. 15 | % 16 | % A=[1 -2.7607 3.8106 -2.6535 0.9238]; 17 | % % Generate noise standard deviations 18 | % % Seed random number generator for reproducible results 19 | % rng default; 20 | % noise_stdz=rand(50,1)+0.5; 21 | % for j=1:50 22 | % y=filter(1,A,noise_stdz(j)*randn(1024,1)); 23 | % [ar_coeffs,NoiseVariance(j)]=arburg(y,4); 24 | % end 25 | % %Compare actual vs. estimated variances 26 | % plot(noise_stdz.^2,NoiseVariance,'k*'); 27 | % xlabel('Input Noise Variance'); 28 | % ylabel('Estimated Noise Variance'); 29 | % 30 | % See also PBURG, ARMCOV, ARCOV, ARYULE, LPC, PRONY. 31 | 32 | % Ref: S. Kay, MODERN SPECTRAL ESTIMATION, 33 | % Prentice-Hall, 1988, Chapter 7 34 | % S. Orfanidis, OPTIMUM SIGNAL PROCESSING, 2nd Ed. 35 | % Macmillan, 1988, Chapter 5 36 | 37 | % Author(s): D. Orofino and R. Losada 38 | % Copyright 1988-2009 The MathWorks, Inc. 39 | % $Revision: 1.12.4.7 $ $Date: 2012/10/29 19:30:37 $ 40 | 41 | error(nargchk(2,2,nargin,'struct')) 42 | 43 | % Check the input data type. Single precision is not supported. 44 | try 45 | chkinputdatatype(x,p); 46 | catch ME 47 | throwAsCaller(ME); 48 | end 49 | 50 | validateattributes(x,{'numeric'},{'nonempty','finite','vector'},'arburg','X'); 51 | validateattributes(p,{'numeric'},{'positive','integer','scalar'},'arburg','ORDER'); 52 | if issparse(x), 53 | error(message('signal:arburg:Sparse')) 54 | end 55 | if numel(x) < p+1 56 | error(message('signal:arburg:InvalidDimension', p + 1)); 57 | end 58 | 59 | x = x(:); 60 | N = length(x); 61 | 62 | % Initialization 63 | ef = x; 64 | eb = x; 65 | a = 1; 66 | 67 | % Initial error 68 | E = x'*x./N; 69 | 70 | % Preallocate 'k' for speed. 71 | k = zeros(1, p); 72 | 73 | for m=1:p 74 | % Calculate the next order reflection (parcor) coefficient 75 | efp = ef(2:end); 76 | ebp = eb(1:end-1); 77 | num = -2.*ebp'*efp; 78 | den = efp'*efp+ebp'*ebp; 79 | 80 | k(m) = num ./ den; 81 | 82 | % Update the forward and backward prediction errors 83 | ef = efp + k(m)*ebp; 84 | eb = ebp + k(m)'*efp; 85 | 86 | % Update the AR coeff. 87 | a=[a;0] + k(m)*[0;conj(flipud(a))]; 88 | 89 | % Update the prediction error 90 | E(m+1) = (1 - k(m)'*k(m))*E(m); 91 | end 92 | 93 | a = a(:).'; % By convention all polynomials are row vectors 94 | varargout{1} = a; 95 | if nargout >= 2 96 | varargout{2} = E(end); 97 | end 98 | if nargout >= 3 99 | varargout{3} = k(:); 100 | end 101 | -------------------------------------------------------------------------------- /matlab_test_files/arburg_test.m: -------------------------------------------------------------------------------- 1 | function varargout = arburg( x, p) 2 | %ARBURG AR parameter estimation via Burg method. 3 | % A = ARBURG(X,ORDER) returns the polynomial A corresponding to the AR 4 | % parametric signal model estimate of vector X using Burg's method. 5 | % ORDER is the model order of the AR system. 6 | % 7 | % [A,E] = ARBURG(...) returns the final prediction error E (the variance 8 | % estimate of the white noise input to the AR model). 9 | % 10 | % [A,E,K] = ARBURG(...) returns the vector K of reflection 11 | % coefficients (parcor coefficients). 12 | % 13 | % % Example: 14 | % % Estimate input noise variance for AR(4) model. 15 | % 16 | % A=[1 -2.7607 3.8106 -2.6535 0.9238]; 17 | % % Generate noise standard deviations 18 | % % Seed random number generator for reproducible results 19 | % rng default; 20 | % noise_stdz=rand(50,1)+0.5; 21 | % for j=1:50 22 | % y=filter(1,A,noise_stdz(j)*randn(1024,1)); 23 | % [ar_coeffs,NoiseVariance(j)]=arburg(y,4); 24 | % end 25 | % %Compare actual vs. estimated variances 26 | % plot(noise_stdz.^2,NoiseVariance,'k*'); 27 | % xlabel('Input Noise Variance'); 28 | % ylabel('Estimated Noise Variance'); 29 | % 30 | % See also PBURG, ARMCOV, ARCOV, ARYULE, LPC, PRONY. 31 | 32 | % Ref: S. Kay, MODERN SPECTRAL ESTIMATION, 33 | % Prentice-Hall, 1988, Chapter 7 34 | % S. Orfanidis, OPTIMUM SIGNAL PROCESSING, 2nd Ed. 35 | % Macmillan, 1988, Chapter 5 36 | 37 | % Author(s): D. Orofino and R. Losada 38 | % Copyright 1988-2009 The MathWorks, Inc. 39 | % $Revision: 1.12.4.7 $ $Date: 2012/10/29 19:30:37 $ 40 | 41 | % error(nargchk(2,2,nargin,'struct')) 42 | % 43 | % % Check the input data type. Single precision is not supported. 44 | % try 45 | % chkinputdatatype(x,p); 46 | % catch ME 47 | % throwAsCaller(ME); 48 | % end 49 | % 50 | % validateattributes(x,{'numeric'},{'nonempty','finite','vector'},'arburg','X'); 51 | % validateattributes(p,{'numeric'},{'positive','integer','scalar'},'arburg','ORDER'); 52 | % if issparse(x), 53 | % error(message('signal:arburg:Sparse')) 54 | % end 55 | % if numel(x) < p+1 56 | % error(message('signal:arburg:InvalidDimension', p + 1)); 57 | % end 58 | 59 | x = x(:); 60 | N = length(x); 61 | 62 | % Initialization 63 | ef = x; 64 | eb = x; 65 | a = 1; 66 | 67 | % Initial error 68 | E = x'*x./N; 69 | 70 | % Preallocate 'k' for speed. 71 | k = zeros(1, p); 72 | 73 | for m=1:p 74 | % Calculate the next order reflection (parcor) coefficient 75 | efp = ef(2:end); 76 | ebp = eb(1:end-1); 77 | num = -2.*ebp'*efp; 78 | den = efp'*efp+ebp'*ebp; 79 | 80 | k(m) = num ./ den; 81 | 82 | % Update the forward and backward prediction errors 83 | ef = efp + k(m)*ebp; 84 | eb = ebp + k(m)'*efp; 85 | 86 | % Update the AR coeff. 87 | a=[a;0] + k(m)*[0;conj(flipud(a))]; 88 | 89 | % Update the prediction error 90 | E(m+1) = (1 - k(m)'*k(m))*E(m); 91 | end 92 | 93 | a = a(:).'; % By convention all polynomials are row vectors 94 | varargout{1} = a; 95 | if nargout >= 2 96 | varargout{2} = E(end); 97 | end 98 | if nargout >= 3 99 | varargout{3} = k(:); 100 | end 101 | -------------------------------------------------------------------------------- /matlab_test_files/arburg_test2.m: -------------------------------------------------------------------------------- 1 | function varargout = arburg( x, p) 2 | %ARBURG AR parameter estimation via Burg method. 3 | % A = ARBURG(X,ORDER) returns the polynomial A corresponding to the AR 4 | % parametric signal model estimate of vector X using Burg's method. 5 | % ORDER is the model order of the AR system. 6 | % 7 | % [A,E] = ARBURG(...) returns the final prediction error E (the variance 8 | % estimate of the white noise input to the AR model). 9 | % 10 | % [A,E,K] = ARBURG(...) returns the vector K of reflection 11 | % coefficients (parcor coefficients). 12 | % 13 | % % Example: 14 | % % Estimate input noise variance for AR(4) model. 15 | % 16 | % A=[1 -2.7607 3.8106 -2.6535 0.9238]; 17 | % % Generate noise standard deviations 18 | % % Seed random number generator for reproducible results 19 | % rng default; 20 | % noise_stdz=rand(50,1)+0.5; 21 | % for j=1:50 22 | % y=filter(1,A,noise_stdz(j)*randn(1024,1)); 23 | % [ar_coeffs,NoiseVariance(j)]=arburg(y,4); 24 | % end 25 | % %Compare actual vs. estimated variances 26 | % plot(noise_stdz.^2,NoiseVariance,'k*'); 27 | % xlabel('Input Noise Variance'); 28 | % ylabel('Estimated Noise Variance'); 29 | % 30 | % See also PBURG, ARMCOV, ARCOV, ARYULE, LPC, PRONY. 31 | 32 | % Ref: S. Kay, MODERN SPECTRAL ESTIMATION, 33 | % Prentice-Hall, 1988, Chapter 7 34 | % S. Orfanidis, OPTIMUM SIGNAL PROCESSING, 2nd Ed. 35 | % Macmillan, 1988, Chapter 5 36 | 37 | % Author(s): D. Orofino and R. Losada 38 | % Copyright 1988-2009 The MathWorks, Inc. 39 | % $Revision: 1.12.4.7 $ $Date: 2012/10/29 19:30:37 $ 40 | 41 | % error(nargchk(2,2,nargin,'struct')) 42 | % 43 | % % Check the input data type. Single precision is not supported. 44 | % try 45 | % chkinputdatatype(x,p); 46 | % catch ME 47 | % throwAsCaller(ME); 48 | % end 49 | % 50 | % validateattributes(x,{'numeric'},{'nonempty','finite','vector'},'arburg','X'); 51 | % validateattributes(p,{'numeric'},{'positive','integer','scalar'},'arburg','ORDER'); 52 | % if issparse(x), 53 | % error(message('signal:arburg:Sparse')) 54 | % end 55 | % if numel(x) < p+1 56 | % error(message('signal:arburg:InvalidDimension', p + 1)); 57 | % end 58 | 59 | x = x(:); 60 | N = length(x); 61 | 62 | % Initialization 63 | ef = x; 64 | eb = x; 65 | a = 1; 66 | 67 | % Initial error 68 | E = x'*x./N; 69 | 70 | % Preallocate 'k' for speed. 71 | k = zeros(1, p); 72 | 73 | % for m=1:p 74 | % Calculate the next order reflection (parcor) coefficient 75 | efp = ef(2:end); 76 | ebp = eb(1:end-1); 77 | num = -2.*ebp'*efp; 78 | den = efp'*efp+ebp'*ebp; 79 | 80 | k(m) = num ./ den; 81 | 82 | % Update the forward and backward prediction errors 83 | ef = efp + k(m)*ebp; 84 | eb = ebp + k(m)'*efp; 85 | 86 | % Update the AR coeff. 87 | a=[a;0] + k(m)*[0;conj(flipud(a))]; 88 | 89 | % Update the prediction error 90 | E(m+1) = (1 - k(m)'*k(m))*E(m); 91 | % end 92 | 93 | % a = a(:).'; % By convention all polynomials are row vectors 94 | % varargout{1} = a; 95 | % if nargout >= 2 96 | % varargout{2} = E(end); 97 | % end 98 | % if nargout >= 3 99 | % varargout{3} = k(:); 100 | % end 101 | -------------------------------------------------------------------------------- /src/by_hand_code/prony.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # vim: set fileencoding=utf-8 3 | """ This file is a Python translation of the MATLAB file prony.m 4 | 5 | Python version by RDL 12 Jan 2012 6 | Copyright notice from prony.m: 7 | copyright 1996, by M.H. Hayes. For use with the book 8 | "Statistical Digital Signal Processing and Modeling" 9 | (John Wiley & Sons, 1996). 10 | """ 11 | 12 | from __future__ import print_function,division 13 | import sys 14 | import numpy as np 15 | 16 | from convm import convm 17 | 18 | def prony(x, p, q): 19 | """Model a signal using Prony's method 20 | 21 | Usage: [b,a,err] = prony(x,p,q) 22 | 23 | The input sequence x is modeled as the unit sample response of 24 | a filter having a system function of the form 25 | H(z) = B(z)/A(z) 26 | The polynomials B(z) and A(z) are formed from the vectors 27 | b=[b(0), b(1), ... b(q)] 28 | a=[1 , a(1), ... a(p)] 29 | The input q defines the number of zeros in the model 30 | and p defines the number of poles. The modeling error is 31 | returned in err. 32 | 33 | This comes from Hayes, p. 149, 153, etc 34 | 35 | """ 36 | x = x[:] 37 | N = len(x) 38 | if p+q >= len(x): 39 | print('ERROR: model order too large') 40 | print ("p q len(x) " + str(p) + " " + str(q) + " " + str(len(x))) 41 | sys.exit(1) 42 | 43 | # This formulation uses eq. 4.50, p. 153 44 | # Set up the convolution matrices 45 | X = convm(x, p+1) 46 | Xq = X[q:N+p-1, 0:p] 47 | xq1 = -X[q+1:N+p,0] 48 | 49 | # Solve for denominator coefficients 50 | if p>0: 51 | a = np.linalg.lstsq(Xq, xq1)[0] 52 | a = np.insert(a, 0, 1) # a(0) is 1 53 | else: 54 | # all-zero model 55 | a = np.array(1) 56 | 57 | # Solve for the model error 58 | err = np.dot(x[q+1:N].conj().T,X[q+1:N, 0:p+1]) 59 | err = np.dot(err, a) 60 | 61 | # Solve for numerator coefficients 62 | if q>0: 63 | # (This is the same as for Pad?) 64 | b = np.dot(X[0:q+1,0:p+1], a) 65 | else: 66 | # all-pole model 67 | # b(0) is x(0), but a better solution is to match energy 68 | b = np.sqrt(err) 69 | 70 | return (b,a) 71 | 72 | #function [a,b,err] = prony(x,p,q) 73 | #x = x(:); 74 | #N = length(x); 75 | #if p+q>=length(x), error('Model order too large'), end 76 | #X = convm(x,p+1); 77 | #Xq = X(q+1:N+p-1,1:p); 78 | #a = [1;-Xq\X(q+2:N+p,1)]; 79 | #b = X(1:q+1,1:p+1)*a; 80 | #err = x(q+2:N)'*X(q+2:N,1:p+1)*a; 81 | 82 | def main(): 83 | """Test driver""" 84 | # From pp. 149-150 85 | x = np.ones(21) 86 | p = q = 1 87 | print('x: {}\np: {}\nq: {}'.format(x,p,q)) 88 | b,a,err = prony(x, p, q) 89 | print('a: {}\nb: {}\nerr: {}'.format(a,b,err)) 90 | 91 | # From pp. 152-153 92 | # Note that these results don't match the book, but they do match the 93 | # MATLAB version. So I'm either setting things up wrong or this is an 94 | # errata in the book. 95 | p = q = 5 96 | nd = 5 97 | n = np.arange(11) 98 | i = np.sinc((n-nd)/2)/2 99 | b,a,err = prony(i, p, q) 100 | print('a: {}\nb: {}\nerr: {}'.format(a,b,err)) 101 | 102 | if __name__ == '__main__': 103 | main() -------------------------------------------------------------------------------- /matlab_test_files/arburg_test.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | import scipy 4 | import matcompat 5 | 6 | # if available import pylab (from matlibplot) 7 | try: 8 | import matplotlib.pylab as plt 9 | except ImportError: 10 | pass 11 | 12 | def arburg(x, p): 13 | 14 | # Local Variables: a, E, efp, k, ef, m, varargout, N, p, num, ebp, den, x, eb 15 | # Function calls: arburg, flipud, nargout, length, zeros, conj 16 | #%ARBURG AR parameter estimation via Burg method. 17 | #% A = ARBURG(X,ORDER) returns the polynomial A corresponding to the AR 18 | #% parametric signal model estimate of vector X using Burg's method. 19 | #% ORDER is the model order of the AR system. 20 | #% 21 | #% [A,E] = ARBURG(...) returns the final prediction error E (the variance 22 | #% estimate of the white noise input to the AR model). 23 | #% 24 | #% [A,E,K] = ARBURG(...) returns the vector K of reflection 25 | #% coefficients (parcor coefficients). 26 | #% 27 | #% % Example: 28 | #% % Estimate input noise variance for AR(4) model. 29 | #% 30 | #% A=[1 -2.7607 3.8106 -2.6535 0.9238]; 31 | #% % Generate noise standard deviations 32 | #% % Seed random number generator for reproducible results 33 | #% rng default; 34 | #% noise_stdz=rand(50,1)+0.5; 35 | #% for j=1:50 36 | #% y=filter(1,A,noise_stdz(j)*randn(1024,1)); 37 | #% [ar_coeffs,NoiseVariance(j)]=arburg(y,4); 38 | #% end 39 | #% %Compare actual vs. estimated variances 40 | #% plot(noise_stdz.^2,NoiseVariance,'k*'); 41 | #% xlabel('Input Noise Variance'); 42 | #% ylabel('Estimated Noise Variance'); 43 | #% 44 | #% See also PBURG, ARMCOV, ARCOV, ARYULE, LPC, PRONY. 45 | #% Ref: S. Kay, MODERN SPECTRAL ESTIMATION, 46 | #% Prentice-Hall, 1988, Chapter 7 47 | #% S. Orfanidis, OPTIMUM SIGNAL PROCESSING, 2nd Ed. 48 | #% Macmillan, 1988, Chapter 5 49 | #% Author(s): D. Orofino and R. Losada 50 | #% Copyright 1988-2009 The MathWorks, Inc. 51 | #% $Revision: 1.12.4.7 $ $Date: 2012/10/29 19:30:37 $ 52 | #% error(nargchk(2,2,nargin,'struct')) 53 | #% 54 | #% % Check the input data type. Single precision is not supported. 55 | #% try 56 | #% chkinputdatatype(x,p); 57 | #% catch ME 58 | #% throwAsCaller(ME); 59 | #% end 60 | #% 61 | #% validateattributes(x,{'numeric'},{'nonempty','finite','vector'},'arburg','X'); 62 | #% validateattributes(p,{'numeric'},{'positive','integer','scalar'},'arburg','ORDER'); 63 | #% if issparse(x), 64 | #% error(message('signal:arburg:Sparse')) 65 | #% end 66 | #% if numel(x) < p+1 67 | #% error(message('signal:arburg:InvalidDimension', p + 1)); 68 | #% end 69 | x = x.flatten(1) 70 | N = length(x) 71 | #% Initialization 72 | ef = x 73 | eb = x 74 | a = 1. 75 | #% Initial error 76 | E = np.dot(x.conj().T, x)/N 77 | #% Preallocate 'k' for speed. 78 | k = np.zeros(1., p) 79 | for m in np.arange(1., (p)+1): 80 | #% Calculate the next order reflection (parcor) coefficient 81 | 82 | a = a.flatten(0) 83 | #% By convention all polynomials are row vectors 84 | varargout.cell[0] = a 85 | if nargout >= 2.: 86 | varargout.cell[1] = E[int(0)-1] 87 | 88 | 89 | if nargout >= 3.: 90 | varargout.cell[2] = k.flatten(1) 91 | 92 | 93 | return [varargout] -------------------------------------------------------------------------------- /matlab_test_files/arburg.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | import scipy 4 | import matcompat 5 | 6 | # if available import pylab (from matlibplot) 7 | try: 8 | import matplotlib.pylab as plt 9 | except ImportError: 10 | pass 11 | 12 | def arburg(x, p): 13 | 14 | # Local Variables: a, E, efp, k, ef, m, varargout, N, p, num, ebp, den, x, eb 15 | # Function calls: arburg, validateattributes, nargchk, flipud, nargout, issparse, nargin, length, zeros, numel, error, message, conj 16 | #%ARBURG AR parameter estimation via Burg method. 17 | #% A = ARBURG(X,ORDER) returns the polynomial A corresponding to the AR 18 | #% parametric signal model estimate of vector X using Burg's method. 19 | #% ORDER is the model order of the AR system. 20 | #% 21 | #% [A,E] = ARBURG(...) returns the final prediction error E (the variance 22 | #% estimate of the white noise input to the AR model). 23 | #% 24 | #% [A,E,K] = ARBURG(...) returns the vector K of reflection 25 | #% coefficients (parcor coefficients). 26 | #% 27 | #% % Example: 28 | #% % Estimate input noise variance for AR(4) model. 29 | #% 30 | #% A=[1 -2.7607 3.8106 -2.6535 0.9238]; 31 | #% % Generate noise standard deviations 32 | #% % Seed random number generator for reproducible results 33 | #% rng default; 34 | #% noise_stdz=rand(50,1)+0.5; 35 | #% for j=1:50 36 | #% y=filter(1,A,noise_stdz(j)*randn(1024,1)); 37 | #% [ar_coeffs,NoiseVariance(j)]=arburg(y,4); 38 | #% end 39 | #% %Compare actual vs. estimated variances 40 | #% plot(noise_stdz.^2,NoiseVariance,'k*'); 41 | #% xlabel('Input Noise Variance'); 42 | #% ylabel('Estimated Noise Variance'); 43 | #% 44 | #% See also PBURG, ARMCOV, ARCOV, ARYULE, LPC, PRONY. 45 | #% Ref: S. Kay, MODERN SPECTRAL ESTIMATION, 46 | #% Prentice-Hall, 1988, Chapter 7 47 | #% S. Orfanidis, OPTIMUM SIGNAL PROCESSING, 2nd Ed. 48 | #% Macmillan, 1988, Chapter 5 49 | #% Author(s): D. Orofino and R. Losada 50 | #% Copyright 1988-2009 The MathWorks, Inc. 51 | #% $Revision: 1.12.4.7 $ $Date: 2012/10/29 19:30:37 $ 52 | matcompat.error(nargchk(2., 2., nargin, 'struct')) 53 | #% Check the input data type. Single precision is not supported. 54 | #%try 55 | #% chkinputdatatype(x,p); 56 | #%catch ME 57 | #% throwAsCaller(ME); 58 | #%end 59 | validateattributes(x, cellarray(np.hstack(('numeric'))), cellarray(np.hstack(('nonempty', 'finite', 'vector'))), 'arburg', 'X') 60 | validateattributes(p, cellarray(np.hstack(('numeric'))), cellarray(np.hstack(('positive', 'integer', 'scalar'))), 'arburg', 'ORDER') 61 | if issparse(x): 62 | matcompat.error(message('signal:arburg:Sparse')) 63 | 64 | 65 | if numel(x)= 2.: 86 | varargout.cell[1] = E[int(0)-1] 87 | 88 | 89 | if nargout >= 3.: 90 | varargout.cell[2] = k.flatten(1) 91 | 92 | 93 | return [varargout] -------------------------------------------------------------------------------- /src/by_hand_code/prony_matlab.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sun Jan 6 20:54:46 2014 5 | 6 | @author: Sammy Pfeiffer 7 | This file pretends to imitate the behaviour of the MATLAB function prony 8 | """ 9 | 10 | from scipy.linalg import toeplitz 11 | import numpy as np 12 | 13 | # function [b,a] = prony(h, nb ,na) 14 | def prony_matlab(h, nb, na): 15 | # %PRONY Prony's method for time-domain IIR filter design. 16 | # % [B,A] = PRONY(H, NB, NA) finds a filter with numerator order 17 | # % NB, denominator order NA, and having the impulse response in 18 | # % vector H. The IIR filter coefficients are returned in 19 | # % length NB+1 and NA+1 row vectors B and A, ordered in 20 | # % descending powers of Z. H may be real or complex. 21 | # % 22 | # % If the largest order specified is greater than the length of H, 23 | # % H is padded with zeros. 24 | # % 25 | # % % Example: 26 | # % % Fit an IIR model to an impulse response of a lowpass filter. 27 | # % 28 | # % [b,a] = butter(4,0.2); 29 | # % impulseResp = impz(b,a); % obtain impulse response 30 | # % denOrder=4; numOrder=4; % system function of order 4 31 | # % [Num,Den]=prony(impulseResp,numOrder,denOrder); 32 | # % subplot(211); % impulse response and input 33 | # % stem(impz(Num,Den,length(impulseResp))); 34 | # % title('Impulse Response with Prony Design'); 35 | # % subplot(212); 36 | # % stem(impulseResp); title('Input Impulse Response'); 37 | # % 38 | # % See also STMCB, LPC, BUTTER, CHEBY1, CHEBY2, ELLIP, INVFREQZ. 39 | # 40 | # % Author(s): L. Shure, 5-17-88 41 | # % L. Shure, 12-17-90, revised 42 | # % Copyright 1988-2012 The MathWorks, Inc. 43 | # % $Revision: 1.7.4.1.2.1 $ $Date: 2013/01/02 17:47:48 $ 44 | # 45 | # % References: 46 | # % [1] T.W. Parks and C.S. Burrus, Digital Filter Design, 47 | # % John Wiley and Sons, 1987, p226. 48 | # 49 | # K = length(h) - 1; 50 | # M = nb; N = na; 51 | K = len(h) - 1 52 | M = nb 53 | N = na 54 | # if K <= max(M,N) % zero-pad input if necessary 55 | # K = max(M,N)+1; 56 | # h(K+1) = 0; 57 | # end 58 | if K <= max(M,N): 59 | K = max(M,N) + 1 60 | h[K+1] = 0 # probable problem with indices! 61 | # c = h(1); 62 | c = h[0] # probable problem with indices! 63 | # if c==0 % avoid divide by zero 64 | # c=1; 65 | # end 66 | if c == 0: 67 | c = 1 68 | # H = toeplitz(h/c,[1 zeros(1,K)]); 69 | second_part_toeplitz = np.zeros(K+1) 70 | second_part_toeplitz[0] = 1 71 | H = toeplitz(h/c, second_part_toeplitz) # probable problem with indices! 72 | print "H is (toeplitz...)" 73 | print H 74 | # The size of H is different... cause it comes from before different in h 75 | # % K+1 by N+1 76 | # if (K > N) 77 | # H(:,(N+2):(K+1)) = []; 78 | # end 79 | if K > N: 80 | H = H[:,0:N+1] # Here we are just getting rid of all the columns after N+1 81 | 82 | # % Partition H matrix 83 | # H1 = H(1:(M+1),:); % M+1 by N+1 84 | H1 = H[0:M+1,:] 85 | # h1 = H((M+2):(K+1),1); % K-M by 1 86 | h1 = H[M+1:K+1,0] 87 | # H2 = H((M+2):(K+1),2:(N+1)); % K-M by N 88 | H2 = H[M:K,0:N] 89 | # a = [1; -H2\h1].'; 90 | #\ 91 | # Matrix left division 92 | # x = A\B is the solution to the equation Ax = B. Matrices A and B must have the same number of rows. 93 | #H2 and h1 won't make ever a square (I think) matrix so I will just solve with least squares 94 | a_right = np.linalg.lstsq(-H2,h1)[0] 95 | a_left = np.array([1]) 96 | a = np.append(a_left, a_right) 97 | 98 | # b = c*a*H1.'; 99 | b = c*(H1.dot(a)) 100 | 101 | return [b, a] -------------------------------------------------------------------------------- /src/prony.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sun Jan 6 20:54:46 2014 5 | Redone on Jan 22 12:00:00 2014 6 | 7 | @author: Sammy Pfeiffer 8 | @email: sammypfeiffer@gmail.com 9 | This file pretends to imitate the behavior of the MATLAB function prony 10 | """ 11 | import numpy as np 12 | from scipy.linalg import toeplitz 13 | 14 | 15 | def prony(h, nb, na): 16 | """From MATLAB: 17 | %PRONY Prony's method for time-domain IIR filter design. 18 | % [B,A] = PRONY(H, NB, NA) finds a filter with numerator order 19 | % NB, denominator order NA, and having the impulse response in 20 | % vector H. The IIR filter coefficients are returned in 21 | % length NB+1 and NA+1 row vectors B and A, ordered in 22 | % descending powers of Z. H may be real or complex. 23 | % 24 | % If the largest order specified is greater than the length of H, 25 | % H is padded with zeros. 26 | """ 27 | 28 | # Local Variables: a, c, b, h1, h, nb, H1, M, N, H2, H, na, H2_minus, K 29 | # Function calls: max, length, prony, zeros, toeplitz 30 | #%PRONY Prony's method for time-domain IIR filter design. 31 | #% [B,A] = PRONY(H, NB, NA) finds a filter with numerator order 32 | #% NB, denominator order NA, and having the impulse response in 33 | #% vector H. The IIR filter coefficients are returned in 34 | #% length NB+1 and NA+1 row vectors B and A, ordered in 35 | #% descending powers of Z. H may be real or complex. 36 | #% 37 | #% If the largest order specified is greater than the length of H, 38 | #% H is padded with zeros. 39 | #% 40 | #% % Example: 41 | #% % Fit an IIR model to an impulse response of a lowpass filter. 42 | #% 43 | #% [b,a] = butter(4,0.2); 44 | #% impulseResp = impz(b,a); % obtain impulse response 45 | #% denOrder=4; numOrder=4; % system function of order 4 46 | #% [Num,Den]=prony(impulseResp,numOrder,denOrder); 47 | #% subplot(211); % impulse response and input 48 | #% stem(impz(Num,Den,length(impulseResp))); 49 | #% title('Impulse Response with Prony Design'); 50 | #% subplot(212); 51 | #% stem(impulseResp); title('Input Impulse Response'); 52 | #% 53 | #% See also STMCB, LPC, BUTTER, CHEBY1, CHEBY2, ELLIP, INVFREQZ. 54 | #% Author(s): L. Shure, 47-88 55 | #% L. Shure, 117-90, revised 56 | #% Copyright 1988-2012 The MathWorks, Inc. 57 | #% $Revision: 1.7.4.1.2.1 $ $Date: 2013/01/02 17:47:48 $ 58 | #% References: 59 | #% [1] T.W. Parks and C.S. Burrus, Digital Filter Design, 60 | #% John Wiley and Sons, 1987, p226. 61 | K = len(h)-1 62 | M = nb 63 | N = na 64 | if K<=max(M, N): 65 | #% zero-pad input if necessary 66 | K = max(M, N)+1 67 | h[K+1] = 0 68 | 69 | c = h[0] 70 | if c == 0: 71 | #% avoid divide by zero 72 | c = 1 73 | 74 | # second_part_toeplitz = np.zeros(K+1) 75 | # second_part_toeplitz[0] = 1 76 | H = toeplitz(h / c, np.array(np.hstack((1, np.zeros(K))))) 77 | #% K+1 by N+1 78 | if K > N: 79 | #H[:,int(N+2)-1:K+1] = np.array([]) 80 | H = H[:,0:N+1] # Here we are just getting rid of all the columns after N+1 81 | 82 | 83 | #% Partition H matrix 84 | H1 = H[0:M+1,:] 85 | #% M+1 by N+1 86 | h1 = H[M+1:K+1,0] 87 | #% K-M by 1 88 | H2 = H[M:K,0:N] 89 | #% K-M by N 90 | H2_minus = -H2 91 | a_right = np.linalg.lstsq(-H2,h1)[0] 92 | a_left = np.array([1]) 93 | a = np.append(a_left, a_right) 94 | #a = np.array(np.vstack((np.hstack((1)), np.hstack((solve(H2_minus, h1)))))).T 95 | b = np.dot(np.dot(c, a), H1.T) 96 | return [b, a] -------------------------------------------------------------------------------- /matlab_test_files/arburg_test2.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | import scipy 4 | import matcompat 5 | 6 | # if available import pylab (from matlibplot) 7 | try: 8 | import matplotlib.pylab as plt 9 | except ImportError: 10 | pass 11 | 12 | def arburg(x, p): 13 | 14 | # Local Variables: a, E, efp, k, ef, varargout, N, p, num, ebp, den, x, eb 15 | # Function calls: arburg, flipud, m, length, zeros, conj 16 | #%ARBURG AR parameter estimation via Burg method. 17 | #% A = ARBURG(X,ORDER) returns the polynomial A corresponding to the AR 18 | #% parametric signal model estimate of vector X using Burg's method. 19 | #% ORDER is the model order of the AR system. 20 | #% 21 | #% [A,E] = ARBURG(...) returns the final prediction error E (the variance 22 | #% estimate of the white noise input to the AR model). 23 | #% 24 | #% [A,E,K] = ARBURG(...) returns the vector K of reflection 25 | #% coefficients (parcor coefficients). 26 | #% 27 | #% % Example: 28 | #% % Estimate input noise variance for AR(4) model. 29 | #% 30 | #% A=[1 -2.7607 3.8106 -2.6535 0.9238]; 31 | #% % Generate noise standard deviations 32 | #% % Seed random number generator for reproducible results 33 | #% rng default; 34 | #% noise_stdz=rand(50,1)+0.5; 35 | #% for j=1:50 36 | #% y=filter(1,A,noise_stdz(j)*randn(1024,1)); 37 | #% [ar_coeffs,NoiseVariance(j)]=arburg(y,4); 38 | #% end 39 | #% %Compare actual vs. estimated variances 40 | #% plot(noise_stdz.^2,NoiseVariance,'k*'); 41 | #% xlabel('Input Noise Variance'); 42 | #% ylabel('Estimated Noise Variance'); 43 | #% 44 | #% See also PBURG, ARMCOV, ARCOV, ARYULE, LPC, PRONY. 45 | #% Ref: S. Kay, MODERN SPECTRAL ESTIMATION, 46 | #% Prentice-Hall, 1988, Chapter 7 47 | #% S. Orfanidis, OPTIMUM SIGNAL PROCESSING, 2nd Ed. 48 | #% Macmillan, 1988, Chapter 5 49 | #% Author(s): D. Orofino and R. Losada 50 | #% Copyright 1988-2009 The MathWorks, Inc. 51 | #% $Revision: 1.12.4.7 $ $Date: 2012/10/29 19:30:37 $ 52 | #% error(nargchk(2,2,nargin,'struct')) 53 | #% 54 | #% % Check the input data type. Single precision is not supported. 55 | #% try 56 | #% chkinputdatatype(x,p); 57 | #% catch ME 58 | #% throwAsCaller(ME); 59 | #% end 60 | #% 61 | #% validateattributes(x,{'numeric'},{'nonempty','finite','vector'},'arburg','X'); 62 | #% validateattributes(p,{'numeric'},{'positive','integer','scalar'},'arburg','ORDER'); 63 | #% if issparse(x), 64 | #% error(message('signal:arburg:Sparse')) 65 | #% end 66 | #% if numel(x) < p+1 67 | #% error(message('signal:arburg:InvalidDimension', p + 1)); 68 | #% end 69 | x = x.flatten(1) 70 | N = length(x) 71 | #% Initialization 72 | ef = x 73 | eb = x 74 | a = 1. 75 | #% Initial error 76 | E = np.dot(x.conj().T, x)/N 77 | #% Preallocate 'k' for speed. 78 | k = np.zeros(1., p) 79 | #% for m=1:p 80 | #% Calculate the next order reflection (parcor) coefficient 81 | efp = ef[1:] 82 | ebp = eb[0:0-1.] 83 | num = np.dot(np.dot(-2., ebp.conj().T), efp) 84 | den = np.dot(efp.conj().T, efp)+np.dot(ebp.conj().T, ebp) 85 | k[int(m)-1] = num/den 86 | #% Update the forward and backward prediction errors 87 | ef = efp+np.dot(k[int(m)-1], ebp) 88 | eb = ebp+np.dot(k[int(m)-1].conj().T, efp) 89 | #% Update the AR coeff. 90 | a = np.array(np.vstack((np.hstack((a)), np.hstack((0.)))))+np.dot(k[int(m)-1], np.array(np.vstack((np.hstack((0.)), np.hstack((np.conj(np.flipud(a)))))))) 91 | #% Update the prediction error 92 | E[int((m+1.))-1] = np.dot(1.-np.dot(k[int(m)-1].conj().T, k[int(m)-1]), E[int(m)-1]) 93 | #% end 94 | #% a = a(:).'; % By convention all polynomials are row vectors 95 | #% varargout{1} = a; 96 | #% if nargout >= 2 97 | #% varargout{2} = E(end); 98 | #% end 99 | #% if nargout >= 3 100 | #% varargout{3} = k(:); 101 | #% end 102 | return [varargout] -------------------------------------------------------------------------------- /matlab_test_files/stmcb_to_py.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | import scipy 4 | import matcompat 5 | 6 | # if available import pylab (from matlibplot) 7 | try: 8 | import matplotlib.pylab as plt 9 | except ImportError: 10 | pass 11 | 12 | def stmcb(x, u_in, q, p, niter, a_in): 13 | 14 | # Local Variables: T_sub2, T_sub1, T_minus, C2, C1, a_in, N, u_in, T, a, niter, c, b, i, q, p, u, v, x, T_left, T_right, C1_minus 15 | # Function calls: convmtx, filter, prony, nargchk, stmcb, nargin, length, zeros, error, message, size 16 | #%STMCB Compute linear model via Steiglitz-McBride iteration 17 | #% [B,A] = stmcb(H,NB,NA) finds the coefficients of the system 18 | #% B(z)/A(z) with approximate impulse response H, NA poles and 19 | #% NB zeros. 20 | #% 21 | #% [B,A] = stmcb(H,NB,NA,N) uses N iterations. N defaults to 5. 22 | #% 23 | #% [B,A] = stmcb(H,NB,NA,N,Ai) uses the vector Ai as the initial 24 | #% guess at the denominator coefficients. If you don't specify Ai, 25 | #% STMCB uses [B,Ai] = PRONY(H,0,NA) as the initial conditions. 26 | #% 27 | #% [B,A] = STMCB(Y,X,NB,NA,N,Ai) finds the system coefficients B and 28 | #% A of the system which, given X as input, has Y as output. N and Ai 29 | #% are again optional with default values of N = 5, [B,Ai] = PRONY(Y,0,NA). 30 | #% Y and X must be the same length. 31 | #% 32 | #% % Example: 33 | #% % Approximate the impulse response of a Butterworth filter with a 34 | #% % system of lower order. 35 | #% 36 | #% [b,a] = butter(6,0.2); % Butterworth filter design 37 | #% h = filter(b,a,[1 zeros(1,100)]); % Filter data using above filter 38 | #% freqz(b,a,128) % Frequency response 39 | #% [bb,aa] = stmcb(h,4,4); 40 | #% figure; freqz(bb,aa,128) 41 | #% 42 | #% See also PRONY, LEVINSON, LPC, ARYULE. 43 | #% Author(s): Jim McClellan, 2-89 44 | #% T. Krauss, 4-22-93, new help and options 45 | #% Copyright 1988-2004 The MathWorks, Inc. 46 | #% $Revision: 1.8.4.6 $ $Date: 2012/10/29 19:32:10 $ 47 | matcompat.error(nargchk(3., 6., nargin, 'struct')) 48 | if length(u_in) == 1.: 49 | if nargin == 3.: 50 | niter = 5. 51 | p = q 52 | q = u_in 53 | a_in = prony(x, 0., p) 54 | elif nargin == 4.: 55 | niter = p 56 | p = q 57 | q = u_in 58 | a_in = prony(x, 0., p) 59 | 60 | elif nargin == 5.: 61 | a_in = niter 62 | niter = p 63 | p = q 64 | q = u_in 65 | 66 | 67 | u_in = np.zeros(matcompat.size(x)) 68 | u_in[0] = 1. 69 | #% make a unit impulse whose length is same as x 70 | else: 71 | if length(u_in) != length(x): 72 | matcompat.error(message('signal:stmcb:InvalidDimensions')) 73 | 74 | 75 | if nargin<6.: 76 | [b, a_in] = prony(x, 0., p) 77 | 78 | 79 | if nargin<5.: 80 | niter = 5. 81 | 82 | 83 | 84 | 85 | a = a_in 86 | N = length(x) 87 | for i in np.arange(1., (niter)+1): 88 | u = filter(1., a, x) 89 | v = filter(1., a, u_in) 90 | C1 = convmtx(u.flatten(1), (p+1.)) 91 | C2 = convmtx(v.flatten(1), (q+1.)) 92 | C1_minus = -C1 93 | T_sub1 = C1_minus[0:N,:] 94 | T_sub2 = C2[0:N,:] 95 | T = np.array(np.hstack((T_sub1, T_sub2))) 96 | #%T = [ C1_minus(1:N,:) C2(1:N,:) ]; 97 | T_minus = -T 98 | T_left = T[:,1:p+q+2.] 99 | T_right = T_minus[:,0] 100 | c = linalg.solve(T_left, T_right) 101 | #% c = T(:,2:p+q+2)\(T_minus(:,1)); % move 1st column to RHS and do least-squares 102 | a = np.array(np.vstack((np.hstack((1.)), np.hstack((c[0:p]))))) 103 | #% denominator coefficients 104 | b = c[int(p+1.)-1:p+q+1.] 105 | #% numerator coefficients 106 | 107 | a = a.T 108 | b = b.T 109 | return [b, a] -------------------------------------------------------------------------------- /src/arparest.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | import scipy 4 | from scipy.sparse import issparse 5 | import matcompat 6 | from matcompat import * 7 | 8 | # if available import pylab (from matlibplot) 9 | try: 10 | import matplotlib.pylab as plt 11 | except ImportError: 12 | pass 13 | 14 | def arparest(x, p, method): 15 | 16 | # Local Variables: a, msgobj, XM, Xc, a_left, a_right, minlength_x, mx, nx, p, x, msg, e, Xc_minus, X1, method, Cz 17 | # Function calls: real, corrmtx, nargchk, getString, min, strcmp, issparse, nargin, length, abs, isempty, error, arparest, message, round, size 18 | #%ARPAREST AR parameter estimation via a specified method. 19 | #% A = ARPAREST(X,ORDER,METHOD) returns the polynomial A corresponding to 20 | #% the AR parametric signal model estimate of vector X using the specified 21 | #% METHOD. ORDER is the model order of the AR system. 22 | #% 23 | #% Supported methods are: 'covariance' and 'modified' although all of the 24 | #% methods of CORRMTX will work. In particular if 'autocorrelation' is 25 | #% used, the results should be the same as those of ARYULE (but slower). 26 | #% 27 | #% [A,E] = ARPAREST(...) returns the variance estimate E of the white noise 28 | #% input to the AR model. 29 | #% Ref: S. Kay, MODERN SPECTRAL ESTIMATION, 30 | #% Prentice-Hall, 1988, Chapter 7 31 | #% S. Marple, DIGITAL SPECTRAL ANALYSIS WITH APPLICATION, 32 | #% Prentice-Hall, 1987, Chapter 8. 33 | #% P. Stoica and R. Moses, INTRODUCTION TO SPECTRAL ANALYSIS, 34 | #% Prentice-Hall, 1997, Chapter 3 35 | #% Author(s): R. Losada and P. Pacheco 36 | #% Copyright 1988-2004 The MathWorks, Inc. 37 | #% $Revision: 1.5.4.3 $ $Date: 2011/05/13 18:13:56 $ 38 | #matcompat.error(nargchk(3., 3., nargin, 'struct')) 39 | #[mx, nx] = matcompat.size(x) 40 | [mx, nx] = x.shape 41 | #% Initialize in case we return early 42 | a = np.array([]) 43 | e = np.array([]) 44 | #% Assign msg in case there are no errors 45 | msg = '' 46 | msgobj = np.array([]) 47 | #% Set up necessary but not sufficient conditions for the correlation 48 | #% matrix to be nonsingular. From (Marple) 49 | _switch_val=method 50 | if False: # switch 51 | pass 52 | elif _switch_val == 'covariance': 53 | minlength_x = 2.*p 54 | elif _switch_val == 'modified': 55 | minlength_x = 3.*p/2. 56 | else: 57 | msgobj = 'signal:arparest:UnknMethod' 58 | msg = msgobj 59 | return [] 60 | 61 | #% Do some data sanity testing 62 | if x==None or len(x) 1.: 63 | if method == 'modified': 64 | msgobj = 'signal:arparest:TooSmallForModel', 'X', '3/2' 65 | msg = msgobj 66 | else: 67 | msgobj = 'signal:arparest:TooSmallForModel', 'X', '2' 68 | msg = msgobj 69 | 70 | 71 | return [] 72 | 73 | 74 | if issparse(x): 75 | msgobj = 'signal:arparest:InputSignalCannotBeSparse' 76 | msg = msgobj 77 | return [] 78 | 79 | 80 | if p==None or p != np.round(p): 81 | msgobj = 'signal:arparest:ModelOrderMustBeInteger' 82 | msg = msgobj 83 | return [] 84 | 85 | 86 | x = x.flatten(1) 87 | #% Generate the appropriate data matrix 88 | XM = corrmtx(x, p, method) 89 | Xc = XM[:,1:] 90 | X1 = XM[:,0] 91 | #% Coefficients estimated via the covariance method 92 | a_left = np.array(np.hstack((1.))) 93 | Xc_minus = -Xc 94 | a_right = linalg.solve(Xc_minus, X1) 95 | a = np.array(np.vstack((np.hstack((a_left)), np.hstack((a_right))))) 96 | #%a = [1; -Xc\X1]; 97 | #% Estimate the input white noise variance 98 | Cz = np.dot(X1.conj().T, Xc) 99 | e = np.dot(X1.conj().T, X1)+np.dot(Cz, a[1:]) 100 | #% Ignore the possible imaginary part due to numerical errors and force 101 | #% the variance estimate of the white noise to be positive 102 | e = np.abs(np.real(e)) 103 | a = a.flatten(0) 104 | #% By convention all polynomials are row vectors 105 | #% [EOF] arparest.m 106 | return [a, e, msg, msgobj] -------------------------------------------------------------------------------- /src/by_hand_code/prony_testing.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sun Jan 5 17:11:46 2014 5 | 6 | @author: Sammy Pfeiffer 7 | This file is a test for using prony python implementation versus MATLAB one. 8 | """ 9 | 10 | import numpy as np 11 | from prony import prony 12 | from prony_matlab import prony_matlab 13 | from scipy.signal import butter, impulse 14 | from impz import impz 15 | 16 | # % % Example: 17 | # % % Fit an IIR model to an impulse response of a lowpass filter. 18 | # % 19 | # % [b,a] = butter(4,0.2); 20 | b, a = butter(4, 0.2) 21 | # MATLAB output 22 | # Python output 23 | 24 | # b = 0.0048 0.0193 0.0289 0.0193 0.0048 25 | #[ 0.00482434 0.01929737 0.02894606 0.01929737 0.00482434] 26 | 27 | # a = 1.0000 -2.3695 2.3140 -1.0547 0.1874 28 | #[ 1. -2.36951301 2.31398841 -1.05466541 0.18737949] 29 | print b 30 | print a 31 | 32 | # % impulseResp = impz(b,a); % obtain impulse response 33 | # 0.00482434335771622 0.0307287177680857 0.0905946819548826 0.167944821844737 0.224641271344028 0.233457187867600 0.193512552162805 0.123765243571016 0.0496036031380585 -0.00850905187491667 -0.0406738350178057 -0.0475631979469677 -0.0368517338223919 -0.0185628385243508 -0.00125221912683403 0.0100331628527336 0.0139990059845164 0.0121118272327115 0.00712186446378598 0.00173298095479121 -0.00222279239538353 -0.00403535730812247 -0.00392509206552861 -0.00263181398008669 -0.000992945935699223 0.000353673136269240 0.00109549708726230 0.00122332129708734 0.000922772684652072 0.000444882357824948 3.79019631817530e-06 -0.000276480597968442 -0.000367601488225979 -0.000310628048735716 -0.000177716344133915 -3.82012617315314e-05 6.19874979750476e-05 0.000106051505667546 0.000100862919097785 6.61282460408185e-05 2.35297812645709e-05 -1.07611182300523e-05 -2.91027199865281e-05 34 | impulseResp = impz(b,a) 35 | print impulseResp 36 | # I used a couple of examples... matlab gave 43 as length we give 64 37 | # python [ 0.00482434 0.03072872 0.09059468 0.16794482 0.22464127] 38 | # matlab 0.00482434335771622 0.0307287177680857 0.0905946819548826 0.167944821844737 0.224641271344028 39 | 40 | # AS I CAN'T GET TO GENERATE THE SAME SIZE FOR THIS EXAMPLE (ITS JUST A EXAMPLE) 41 | # IM HARDCODING THE IMPULSE RESP WITH THE MATLAB OUTPUT 42 | impulseResp = np.array([0.00482434335771622, 0.0307287177680857, 0.0905946819548826, 0.167944821844737, 43 | 0.224641271344028, 0.233457187867600, 0.193512552162805, 0.123765243571016, 44 | 0.0496036031380585, -0.00850905187491667, -0.0406738350178057, -0.0475631979469677, 45 | -0.0368517338223919, -0.0185628385243508, -0.00125221912683403, 0.0100331628527336, 46 | 0.0139990059845164, 0.0121118272327115, 0.00712186446378598, 0.00173298095479121, 47 | -0.00222279239538353, -0.00403535730812247, -0.00392509206552861, -0.00263181398008669, 48 | -0.000992945935699223, 0.000353673136269240, 0.00109549708726230, 0.00122332129708734, 49 | 0.000922772684652072, 0.000444882357824948, 3.79019631817530e-06, -0.000276480597968442, 50 | -0.000367601488225979, -0.000310628048735716, -0.000177716344133915, -3.82012617315314e-05, 51 | 6.19874979750476e-05, 0.000106051505667546, 0.000100862919097785, 6.61282460408185e-05, 52 | 2.35297812645709e-05, -1.07611182300523e-05, -2.91027199865281e-05]) 53 | 54 | 55 | # % denOrder=4; numOrder=4; % system function of order 4 56 | denOrder = 4 57 | numOrder = 4 58 | 59 | # % [Num,Den]=prony(impulseResp,numOrder,denOrder); 60 | #[Num,Den]=prony(impulseResp,numOrder,denOrder) 61 | [Num,Den]=prony_matlab(impulseResp,numOrder,denOrder) 62 | # MATLAB 63 | # Num =0.0048 0.0193 0.0289 0.0193 0.0048 64 | # Den =1.0000 -2.3695 2.3140 -1.0547 0.1874 65 | # Python 66 | # [ 0.00482434 0.01929737 0.02894606 0.01929737 0.00482434] 67 | # [ 1. -2.36951301 2.31398841 -1.05466541 0.18737949] 68 | print "Num:" 69 | print Num 70 | print "Den:" 71 | print Den 72 | 73 | # % subplot(211); % impulse response and input 74 | # % stem(impz(Num,Den,length(impulseResp))); 75 | # % title('Impulse Response with Prony Design'); 76 | # % subplot(212); 77 | # % stem(impulseResp); title('Input Impulse Response'); 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/trashbin/prony_testing.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sun Jan 5 17:11:46 2014 5 | 6 | @author: Sammy Pfeiffer 7 | This file is a test for using prony python implementation versus MATLAB one. 8 | """ 9 | 10 | import numpy as np 11 | from prony import prony 12 | #from prony_matlab import prony_matlab 13 | from scipy.signal import butter, impulse 14 | #from impz import impz 15 | 16 | # % % Example: 17 | # % % Fit an IIR model to an impulse response of a lowpass filter. 18 | # % 19 | # % [b,a] = butter(4,0.2); 20 | b, a = butter(4, 0.2) 21 | # MATLAB output 22 | # Python output 23 | 24 | # b = 0.0048 0.0193 0.0289 0.0193 0.0048 25 | #[ 0.00482434 0.01929737 0.02894606 0.01929737 0.00482434] 26 | 27 | # a = 1.0000 -2.3695 2.3140 -1.0547 0.1874 28 | #[ 1. -2.36951301 2.31398841 -1.05466541 0.18737949] 29 | print b 30 | print a 31 | 32 | # % impulseResp = impz(b,a); % obtain impulse response 33 | # 0.00482434335771622 0.0307287177680857 0.0905946819548826 0.167944821844737 0.224641271344028 0.233457187867600 0.193512552162805 0.123765243571016 0.0496036031380585 -0.00850905187491667 -0.0406738350178057 -0.0475631979469677 -0.0368517338223919 -0.0185628385243508 -0.00125221912683403 0.0100331628527336 0.0139990059845164 0.0121118272327115 0.00712186446378598 0.00173298095479121 -0.00222279239538353 -0.00403535730812247 -0.00392509206552861 -0.00263181398008669 -0.000992945935699223 0.000353673136269240 0.00109549708726230 0.00122332129708734 0.000922772684652072 0.000444882357824948 3.79019631817530e-06 -0.000276480597968442 -0.000367601488225979 -0.000310628048735716 -0.000177716344133915 -3.82012617315314e-05 6.19874979750476e-05 0.000106051505667546 0.000100862919097785 6.61282460408185e-05 2.35297812645709e-05 -1.07611182300523e-05 -2.91027199865281e-05 34 | #impulseResp = impz(b,a) 35 | #print impulseResp 36 | # I used a couple of examples... matlab gave 43 as length we give 64 37 | # python [ 0.00482434 0.03072872 0.09059468 0.16794482 0.22464127] 38 | # matlab 0.00482434335771622 0.0307287177680857 0.0905946819548826 0.167944821844737 0.224641271344028 39 | 40 | # AS I CAN'T GET TO GENERATE THE SAME SIZE FOR THIS EXAMPLE (ITS JUST A EXAMPLE) 41 | # IM HARDCODING THE IMPULSE RESP WITH THE MATLAB OUTPUT 42 | impulseResp = np.array([0.00482434335771622, 0.0307287177680857, 0.0905946819548826, 0.167944821844737, 43 | 0.224641271344028, 0.233457187867600, 0.193512552162805, 0.123765243571016, 44 | 0.0496036031380585, -0.00850905187491667, -0.0406738350178057, -0.0475631979469677, 45 | -0.0368517338223919, -0.0185628385243508, -0.00125221912683403, 0.0100331628527336, 46 | 0.0139990059845164, 0.0121118272327115, 0.00712186446378598, 0.00173298095479121, 47 | -0.00222279239538353, -0.00403535730812247, -0.00392509206552861, -0.00263181398008669, 48 | -0.000992945935699223, 0.000353673136269240, 0.00109549708726230, 0.00122332129708734, 49 | 0.000922772684652072, 0.000444882357824948, 3.79019631817530e-06, -0.000276480597968442, 50 | -0.000367601488225979, -0.000310628048735716, -0.000177716344133915, -3.82012617315314e-05, 51 | 6.19874979750476e-05, 0.000106051505667546, 0.000100862919097785, 6.61282460408185e-05, 52 | 2.35297812645709e-05, -1.07611182300523e-05, -2.91027199865281e-05]) 53 | 54 | 55 | # % denOrder=4; numOrder=4; % system function of order 4 56 | denOrder = 4 57 | numOrder = 4 58 | 59 | # % [Num,Den]=prony(impulseResp,numOrder,denOrder); 60 | [Num,Den]=prony(impulseResp,numOrder,denOrder) 61 | #[Num,Den]=prony_matlab(impulseResp,numOrder,denOrder) 62 | # MATLAB 63 | # Num =0.0048 0.0193 0.0289 0.0193 0.0048 64 | # Den =1.0000 -2.3695 2.3140 -1.0547 0.1874 65 | # Python 66 | # [ 0.00482434 0.01929737 0.02894606 0.01929737 0.00482434] 67 | # [ 1. -2.36951301 2.31398841 -1.05466541 0.18737949] 68 | print "Num:" 69 | print Num 70 | print "Den:" 71 | print Den 72 | 73 | # % subplot(211); % impulse response and input 74 | # % stem(impz(Num,Den,length(impulseResp))); 75 | # % title('Impulse Response with Prony Design'); 76 | # % subplot(212); 77 | # % stem(impulseResp); title('Input Impulse Response'); 78 | 79 | 80 | -------------------------------------------------------------------------------- /matlab_test_files/arparest_test.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | import scipy 4 | import matcompat 5 | 6 | # if available import pylab (from matlibplot) 7 | try: 8 | import matplotlib.pylab as plt 9 | except ImportError: 10 | pass 11 | 12 | def arparest(x, p, method): 13 | 14 | # Local Variables: a, msgobj, XM, Xc, a_left, a_right, minlength_x, mx, nx, p, x, msg, e, Xc_minus, X1, method, Cz 15 | # Function calls: real, corrmtx, nargchk, getString, min, strcmp, issparse, nargin, length, abs, isempty, error, arparest, message, round, size 16 | #%ARPAREST AR parameter estimation via a specified method. 17 | #% A = ARPAREST(X,ORDER,METHOD) returns the polynomial A corresponding to 18 | #% the AR parametric signal model estimate of vector X using the specified 19 | #% METHOD. ORDER is the model order of the AR system. 20 | #% 21 | #% Supported methods are: 'covariance' and 'modified' although all of the 22 | #% methods of CORRMTX will work. In particular if 'autocorrelation' is 23 | #% used, the results should be the same as those of ARYULE (but slower). 24 | #% 25 | #% [A,E] = ARPAREST(...) returns the variance estimate E of the white noise 26 | #% input to the AR model. 27 | #% Ref: S. Kay, MODERN SPECTRAL ESTIMATION, 28 | #% Prentice-Hall, 1988, Chapter 7 29 | #% S. Marple, DIGITAL SPECTRAL ANALYSIS WITH APPLICATION, 30 | #% Prentice-Hall, 1987, Chapter 8. 31 | #% P. Stoica and R. Moses, INTRODUCTION TO SPECTRAL ANALYSIS, 32 | #% Prentice-Hall, 1997, Chapter 3 33 | #% Author(s): R. Losada and P. Pacheco 34 | #% Copyright 1988-2004 The MathWorks, Inc. 35 | #% $Revision: 1.5.4.3 $ $Date: 2011/05/13 18:13:56 $ 36 | matcompat.error(nargchk(3., 3., nargin, 'struct')) 37 | [mx, nx] = matcompat.size(x) 38 | #% Initialize in case we return early 39 | a = np.array([]) 40 | e = np.array([]) 41 | #% Assign msg in case there are no errors 42 | msg = \' 43 | msgobj = np.array([]) 44 | #% Set up necessary but not sufficient conditions for the correlation 45 | #% matrix to be nonsingular. From (Marple) 46 | _switch_val=method 47 | if False: # switch 48 | pass 49 | elif _switch_val == 'covariance': 50 | minlength_x = 2.*p 51 | elif _switch_val == 'modified': 52 | minlength_x = 3.*p/2. 53 | else: 54 | msgobj = message('signal:arparest:UnknMethod') 55 | msg = getString(msgobj) 56 | return [] 57 | 58 | #% Do some data sanity testing 59 | if isempty(x) or length(x) 1.: 60 | if strcmp(method, 'modified'): 61 | msgobj = message('signal:arparest:TooSmallForModel', 'X', '3/2') 62 | msg = getString(msgobj) 63 | else: 64 | msgobj = message('signal:arparest:TooSmallForModel', 'X', '2') 65 | msg = getString(msgobj) 66 | 67 | 68 | return [] 69 | 70 | 71 | if issparse(x): 72 | msgobj = message('signal:arparest:InputSignalCannotBeSparse') 73 | msg = getString(msgobj) 74 | return [] 75 | 76 | 77 | if isempty(p) or p != np.round(p): 78 | msgobj = message('signal:arparest:ModelOrderMustBeInteger') 79 | msg = getString(msgobj) 80 | return [] 81 | 82 | 83 | x = x.flatten(1) 84 | #% Generate the appropriate data matrix 85 | XM = corrmtx(x, p, method) 86 | Xc = XM[:,1:] 87 | X1 = XM[:,0] 88 | #% Coefficients estimated via the covariance method 89 | a_left = np.array(np.hstack((1.))) 90 | Xc_minus = -Xc 91 | a_right = linalg.solve(Xc_minus, X1) 92 | a = np.array(np.vstack((np.hstack((a_left)), np.hstack((a_right))))) 93 | #%a = [1; -Xc\X1]; 94 | #% Estimate the input white noise variance 95 | Cz = np.dot(X1.conj().T, Xc) 96 | e = np.dot(X1.conj().T, X1)+np.dot(Cz, a[1:]) 97 | #% Ignore the possible imaginary part due to numerical errors and force 98 | #% the variance estimate of the white noise to be positive 99 | e = np.abs(np.real(e)) 100 | a = a.flatten(0) 101 | #% By convention all polynomials are row vectors 102 | #% [EOF] arparest.m 103 | return [a, e, msg, msgobj] -------------------------------------------------------------------------------- /src/by_hand_code/lms.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ LMS adaptive filters """ 3 | from __future__ import print_function, division 4 | __author__ = 'Richard Lindsley' 5 | 6 | import sys 7 | import numpy as np 8 | import matplotlib.pyplot as plt 9 | import convm 10 | 11 | def lms(x, d, p, mu, w0=None): 12 | """ Finds the LMS adaptive filter w based on the inputs 13 | 14 | Adapted from the Hayes MATLAB code. 15 | 16 | Inputs: 17 | x: input data to the filter, Nx1 vector 18 | d: desired output signal, Nx1 vector 19 | p: filter order 20 | mu: step size, scalar or Nx1 vector 21 | w0: initial guess (optional) 22 | 23 | Outputs: 24 | w: filter coefficient matrix: w[n,p] where 25 | n is the time index and 26 | p is the filter tap index 27 | e: error sequence e(n): Nx1 vector 28 | 29 | """ 30 | # Initialize 31 | N = len(x) 32 | X = convm.convm(x, p) 33 | if not w0: 34 | w0 = np.zeros(p) 35 | # Promote mu to be a vector if it's not already 36 | if not isinstance(mu, np.ndarray): 37 | mu = np.ones(N) * mu 38 | w = np.zeros((N,p)) 39 | e = np.zeros(N) 40 | w[0,:] = w0 41 | 42 | # Run the filter 43 | for n in xrange(N-1): 44 | y = np.dot(w[n,:], X[n,:]) 45 | e[n] = d[n] - y 46 | w[n+1,:] = w[n,:] + mu[n] * e[n] * X[n,:].conj() 47 | 48 | return w, e 49 | 50 | def nlms(x, d, p, beta, w0=None, verbose=False): 51 | """ Finds the NLMS adaptive filter w based on the inputs 52 | 53 | Adapted from the Hayes MATLAB code. 54 | 55 | Inputs: 56 | x: input data to the filter, Nx1 vector 57 | d: desired output signal, Nx1 vector 58 | p: filter order 59 | beta: normalized step size (0 < beta < 2) 60 | w0: initial guess (optional) 61 | verbose: verbosity flag 62 | 63 | Outputs: 64 | w: filter coefficient matrix: w[n,p] where 65 | n is the time index and 66 | p is the filter tap index 67 | e: error sequence e(n): Nx1 vector 68 | 69 | """ 70 | # Initialize 71 | N = len(x) 72 | eps = 1e-4 # epsilon for denominator 73 | X = convm.convm(x, p) 74 | if not w0: 75 | w0 = np.zeros(p) 76 | w = np.zeros((N,p)) 77 | e = np.zeros(N) 78 | w[0,:] = w0 79 | if verbose: 80 | print(' ') 81 | 82 | # Run the filter 83 | for n in xrange(N-1): 84 | if verbose and n % 10000 == 0: 85 | print(' {}/{}\r'.format(n,N-1), end='') 86 | sys.stdout.flush() 87 | y = np.dot(w[n,:], X[n,:]) 88 | e[n] = d[n] - y 89 | norm = eps + np.dot(X[n,:], X[n,:].T.conj()) 90 | w[n+1,:] = w[n,:] + beta / norm * e[n] * X[n,:].conj() 91 | 92 | if verbose: 93 | print(' ') 94 | return w, e 95 | 96 | def plot_traj(w, w_true, fname=None): 97 | """ Plot the trajectory of the filter coefficients 98 | 99 | Inputs: 100 | w: matrix of filter weights versus time 101 | w_true: vector of true filter weights 102 | fname: what filename to export the figure to. If None, then doesn't 103 | export 104 | 105 | """ 106 | plt.figure() 107 | n = np.arange(w.shape[0]) 108 | n_ones = np.ones(w.shape[0]) 109 | plt.hold(True) 110 | # NOTE: This construction places a limit of 4 on the filter order 111 | plt_colors = ['b', 'r', 'g', 'k'] 112 | for p in xrange(w.shape[1]): 113 | plt.plot(n, w[:,p], '{}-'.format(plt_colors[p]), label='w({})'.format(p)) 114 | plt.plot(n, w_true[p] * n_ones, '{}--'.format(plt_colors[p])) 115 | plt.xlabel('Iteration') 116 | plt.ylabel('Coefficients') 117 | plt.legend() 118 | if fname: 119 | plt.savefig(fname) 120 | plt.close() 121 | 122 | def plot_error(e, fname=None): 123 | """ Plot the squared error versus time 124 | 125 | Inputs: 126 | e: vector of the error versus time 127 | fname: what filename to export the figure to. If None, then doesn't 128 | export 129 | 130 | """ 131 | plt.figure() 132 | n = np.arange(len(e)) 133 | e2 = np.power(e, 2) 134 | plt.plot(n, e2) 135 | #plt.semilogy(n, e2) 136 | plt.xlabel('Iteration') 137 | plt.ylabel('Squared error') 138 | if fname: 139 | plt.savefig(fname) 140 | plt.close() 141 | -------------------------------------------------------------------------------- /src/aryule.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Jan 22 20:38 2014 5 | 6 | @author: Sammy Pfeiffer 7 | @email: sammypfeiffer@gmail.com 8 | This file pretends to imitate the behaviour of the MATLAB function aryule 9 | 10 | Using spectrum implementation: 11 | http://thomas-cokelaer.info/software/spectrum/html/user/ref_param.html#spectrum.yulewalker.aryule 12 | 13 | """ 14 | import numpy as np 15 | import spectrum 16 | 17 | def aryule(x, p): 18 | """From MATLAB: 19 | % A = ARYULE(X,ORDER) returns the polynomial A corresponding to the AR 20 | % parametric signal model estimate of vector X using the Yule-Walker 21 | % (autocorrelation) method. ORDER is the model order of the AR system. 22 | % This method solves the Yule-Walker equations by means of the Levinson- 23 | % Durbin recursion. 24 | % 25 | % [A,E] = ARYULE(...) returns the final prediction error E (the variance 26 | % estimate of the white noise input to the AR model). 27 | % 28 | % [A,E,K] = ARYULE(...) returns the vector K of reflection coefficients. 29 | 30 | Using spectrum aryule: 31 | def aryule(X, order, norm='biased', allow_singularity=True): 32 | Compute AR coefficients using Yule-Walker method 33 | 34 | :param X: Array of complex data values, X(1) to X(N) 35 | :param int order: Order of autoregressive process to be fitted (integer) 36 | :param str norm: Use a biased or unbiased correlation. 37 | :param bool allow_singularity: 38 | 39 | :return: 40 | * AR coefficients (complex) 41 | * variance of white noise (Real) 42 | * reflection coefficients for use in lattice filter 43 | """ 44 | [A, E, K] = spectrum.aryule(x, p) 45 | A = np.hstack((1, A)) # MATLAB adds the first "1.0" 46 | return A, E, K 47 | 48 | # Local Variables: a, e, k, nx, p, R, x, mx 49 | # Function calls: aryule, nargchk, min, issparse, nargin, length, isempty, error, levinson, message, xcorr, round, size 50 | #%ARYULE AR parameter estimation via Yule-Walker method. 51 | #% A = ARYULE(X,ORDER) returns the polynomial A corresponding to the AR 52 | #% parametric signal model estimate of vector X using the Yule-Walker 53 | #% (autocorrelation) method. ORDER is the model order of the AR system. 54 | #% This method solves the Yule-Walker equations by means of the Levinson- 55 | #% Durbin recursion. 56 | #% 57 | #% [A,E] = ARYULE(...) returns the final prediction error E (the variance 58 | #% estimate of the white noise input to the AR model). 59 | #% 60 | #% [A,E,K] = ARYULE(...) returns the vector K of reflection coefficients. 61 | #% 62 | #% % Example: 63 | #% % Estimate model order using decay of reflection coefficients. 64 | #% 65 | #% rng default; 66 | #% y=filter(1,[1 -0.75 0.5],0.2*randn(1024,1)); 67 | #% 68 | #% % Create AR(2) process 69 | #% [ar_coeffs,NoiseVariance,reflect_coeffs]=aryule(y,10); 70 | #% 71 | #% % Fit AR(10) model 72 | #% stem(reflect_coeffs); axis([-0.05 10.5 -1 1]); 73 | #% title('Reflection Coefficients by Lag'); xlabel('Lag'); 74 | #% ylabel('Reflection Coefficent'); 75 | #% 76 | #% See also PYULEAR, ARMCOV, ARBURG, ARCOV, LPC, PRONY. 77 | #% Ref: S. Orfanidis, OPTIMUM SIGNAL PROCESSING, 2nd Ed. 78 | #% Macmillan, 1988, Chapter 5 79 | #% M. Hayes, STATISTICAL DIGITAL SIGNAL PROCESSING AND MODELING, 80 | #% John Wiley & Sons, 1996, Chapter 8 81 | #% Author(s): R. Losada 82 | #% Copyright 1988-2004 The MathWorks, Inc. 83 | #% $Revision: 1.12.4.6 $ $Date: 2012/10/29 19:30:38 $ 84 | # matcompat.error(nargchk(2., 2., nargin, 'struct')) 85 | # #% Check the input data type. Single precision is not supported. 86 | # #%try 87 | # #% chkinputdatatype(x,p); 88 | # #%catch ME 89 | # #% throwAsCaller(ME); 90 | # #%end 91 | # [mx, nx] = matcompat.size(x) 92 | # if isempty(x) or length(x)

1.: 93 | # matcompat.error(message('signal:aryule:InvalidDimensions')) 94 | # elif isempty(p) or not p == np.round(p): 95 | # matcompat.error(message('signal:aryule:MustBeInteger')) 96 | # 97 | # 98 | # if issparse(x): 99 | # matcompat.error(message('signal:aryule:Sparse')) 100 | # 101 | # 102 | # R = plt.xcorr(x, p, 'biased') 103 | # [a, e, k] = levinson(R[int(p+1.)-1:], p) 104 | # return [a, e, k] -------------------------------------------------------------------------------- /src/by_hand_code/stmbc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Sun Nov 17 12:30:46 2013 5 | 6 | @author: Sammy Pfeiffer 7 | This file pretends to imitate the behaviour of the MATLAB function with the same name. 8 | """ 9 | 10 | from prony_matlab import prony_matlab 11 | from convmtx import convmtx 12 | from scipy.signal import lfilter 13 | import numpy as np 14 | 15 | def stmcb(x, u_in=None, q=None, p=None, niter=5, a_in=None): 16 | """ 17 | %STMCB Compute linear model via Steiglitz-McBride iteration 18 | [B,A] = stmcb(H,NB,NA) finds the coefficients of the system 19 | B(z)/A(z) with approximate impulse response H, NA poles and 20 | NB zeros. 21 | 22 | [B,A] = stmcb(H,NB,NA,N) uses N iterations. N defaults to 5. 23 | 24 | [B,A] = stmcb(H,NB,NA,N,Ai) uses the vector Ai as the initial 25 | guess at the denominator coefficients. If you don't specify Ai, 26 | STMCB uses [B,Ai] = PRONY(H,0,NA) as the initial conditions. 27 | 28 | [B,A] = STMCB(Y,X,NB,NA,N,Ai) finds the system coefficients B and 29 | A of the system which, given X as input, has Y as output. N and Ai 30 | are again optional with default values of N = 5, [B,Ai] = PRONY(Y,0,NA). 31 | Y and X must be the same length. 32 | 33 | % Example: 34 | % Approximate the impulse response of a Butterworth filter with a 35 | % system of lower order. 36 | 37 | [b,a] = butter(6,0.2); % Butterworth filter design 38 | h = filter(b,a,[1 zeros(1,100)]); % Filter data using above filter 39 | freqz(b,a,128) % Frequency response 40 | [bb,aa] = stmcb(h,4,4); 41 | figure; freqz(bb,aa,128) 42 | 43 | See also PRONY, LEVINSON, LPC, ARYULE. 44 | 45 | Author(s): Jim McClellan, 2-89 46 | T. Krauss, 4-22-93, new help and options 47 | Copyright 1988-2004 The MathWorks, Inc. 48 | $Revision: 1.8.4.6 $ $Date: 2012/10/29 19:32:10 $ 49 | """ 50 | 51 | #error(nargchk(3,6,nargin,'struct')) 52 | 53 | #TODO: fit the full definition of the function 54 | # if length(u_in) == 1, 55 | # if nargin == 3, 56 | # niter = 5; p = q; q = u_in; 57 | # a_in = prony(x,0,p); 58 | # elseif nargin == 4, 59 | # niter = p; p = q; q = u_in; 60 | # a_in = prony(x,0,p); 61 | # elseif nargin == 5, 62 | # a_in = niter; niter = p; p = q; q = u_in; 63 | # end 64 | # u_in = zeros(size(x)); 65 | # u_in(1) = 1; % make a unit impulse whose length is same as x 66 | # else 67 | # if length(u_in)~=length(x), 68 | # error(message('signal:stmcb:InvalidDimensions')) 69 | # end 70 | if len(u_in) != len(x): 71 | print "stmbc:" 72 | print "Invalid dimensions on u_in and x, must be of the same size: " + str(len(u_in)) + "!=" + str(len(x)) 73 | exit(0) 74 | # if nargin < 6 75 | # [b,a_in] = prony(x,0,p); 76 | # end 77 | if a_in == None: 78 | [b, a_in] = prony_matlab(x, 0, p) 79 | print "p is:" 80 | print p 81 | print "b is: " 82 | print b 83 | print "a_in is:" 84 | print a_in 85 | # if nargin < 5 86 | # niter = 5; 87 | # end 88 | # nargin already initialized as 5 on function definition, check not necessary 89 | # end 90 | 91 | 92 | 93 | # a = a_in; 94 | # N = length(x); 95 | a = a_in 96 | N = len(x) 97 | # for i=1:niter 98 | for i in range(niter): 99 | # u = filter( 1, a, x ); 100 | print "a is: " + str(a) 101 | ## MATLAB 102 | # a = 103 | # 1.0000 104 | # -1.9803 105 | # 0.9806 106 | # python a is: 1 107 | 108 | #print "x is: " + str(x) 109 | u = lfilter(1, a, x) 110 | print u 111 | exit(0) 112 | # v = filter( 1, a, u_in ); 113 | v = lfilter(1, a, u_in) 114 | # C1 = convmtx(u(:),p+1); 115 | C1 = convmtx(u,p+1) 116 | # C2 = convmtx(v(:),q+1); 117 | C2 = convmtx(v,q+1) 118 | # T = [ -C1(1:N,:) C2(1:N,:) ]; 119 | T = np.array([-C1[0:N,:], 120 | C2[0:N,:]]) 121 | # c = T(:,2:p+q+2)\(-T(:,1)); % move 1st column to RHS and do least-squares 122 | # Si la matriz no es cuadrada: numpy.linalg.lstsq 123 | # Si la matriz es cuadrada: numpy.linalg.solve 124 | if T.shape[0] != T.shape[1]: 125 | c = np.linalg.lstsq(a, b) 126 | 127 | # a = [1; c(1:p)]; % denominator coefficients 128 | # b = c(p+1:p+q+1); % numerator coefficients 129 | # end 130 | # a=a.'; 131 | # b=b.'; 132 | a = b = 0 133 | return b, a -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | parametric_modeling 2 | =================== 3 | 4 | Parametric modelling functions that can be found in MATLAB... now in Python! 5 | (AR, ARMA, frequency response modeling) 6 | The idea is to have all the functions listed at: http://www.mathworks.es/es/help/signal/parametric-modeling.html 7 | 8 | Note about license: All the code I wrote is BSD as stated in the LICENSE file. Any commented/inspired by MATLAB code is of their own property. Given this was a project for university I won't dig further into this issue. If you want to re-use this code, you should research under what conditions you can based on that. 9 | 10 | Right now we have: 11 | 12 | * **arburg** Autoregressive (AR) all-pole model parameters estimated using Burg method 13 | * Working thanks to spectrum arburg (http://thomas-cokelaer.info/software/spectrum/html/user/ref_param.html#spectrum.burg.arburg) 14 | 15 | * **arcov** Estimate AR model parameters using covariance method 16 | * Working thanks to spectrum arcovar (http://thomas-cokelaer.info/software/spectrum/html/user/ref_psd_other.html#spectrum.covar.arcovar) 17 | 18 | * **armcov** Estimate AR model parameters using modified covariance method 19 | * Working thanks to spectrum modcovar (http://thomas-cokelaer.info/software/spectrum/html/user/ref_psd_other.html#spectrum.modcovar.modcovar) 20 | 21 | * **aryule** Estimate autoregressive (AR) all-pole model using Yule-Walker method 22 | * Working thanks to spectrum aryule (http://thomas-cokelaer.info/software/spectrum/html/user/ref_param.html#spectrum.yulewalker.aryule) 23 | 24 | * **invfreqs** Identify continuous-time filter parameters from frequency response data 25 | * Working thanks to a file found at http://projects.scipy.org/scipy/attachment/ticket/393/invfreq.py 26 | 27 | * **invfreqz** Identify discrete-time filter parameters from frequency response data 28 | * Not working :( whenever polystab function in spectrum is implemented this file can be finalized easily (it's nearly done!) Note that I found a maybe working implementation here: https://github.com/yurochka/dsptools/blob/master/dsptools/invfreqz.py 29 | 30 | * **prony** Prony method for filter design 31 | * Working thanks to... me! 32 | 33 | * **stmcb** Compute linear model using Steiglitz-McBride iteration 34 | * Working thanks to... me! 35 | 36 | Also I needed to implement: 37 | 38 | * **convmtx** Convolution matrix 39 | * Working thanks to... me! 40 | 41 | 42 | =================== 43 | 44 | Developed using **Python 2.7, Eclipse + PyDev, MATLAB R2013a 64 bits** 45 | 46 | * Using **numpy 1.6.1** (from ubuntu debs, using Ubuntu 12.04 64 bit) 47 | ``` 48 | sudo apt-get install numpy 49 | ``` 50 | 51 | * Using **scipy 0.13.1** (upgraded it from Ubuntu debs as I needed newer functions and some bugfixes) 52 | ``` 53 | sudo pip install scipy 54 | ``` 55 | 56 | * Using **spectrum 0.5.6** https://pypi.python.org/pypi/spectrum 57 | ``` 58 | sudo pip install spectrum 59 | ``` 60 | 61 | 62 | I wanted to use/integrate in: **python_control**, using a checkout of the most updated branch, can be found at: 63 | https://github.com/awesomebytes/python-control-code 64 | 65 | But I don't have time for now. 66 | 67 | 68 | * For testing purposes using **matlabpipe** from **python-mlabwrap** 69 | 70 | This great library lets you **execute MATLAB code from Python** (easily! check the tests xxxxx_matlab_vs_python.py). 71 | 72 | https://github.com/awesomebytes/python-mlabwrap 73 | 74 | This is a fork from the work of Filipe Fernandes which he forked from http://code.google.com/p/danapeerlab/ 75 | ``` 76 | git clone https://github.com/awesomebytes/python-mlabwrap 77 | cd python-mlwrap 78 | sudo python setup.py install 79 | ``` 80 | 81 | Thanks to this tool I can test the behaviour of my functions versus the MATLAB functions 82 | and also give the same input data without needing to implement lots of other functions. 83 | 84 | * Also another incredible tool is **libermate** http://libermate.sourceforge.net/ 85 | 86 | **A MATLAB to Python code translator** which doesn't do all the job but helps 87 | 88 | I've rehosted it now in Github https://github.com/awesomebytes/libermate to give it more visibility and 89 | add it's README to it and my advice on how to use it if you ever want to translate a MATLAB script to Python. 90 | 91 | Guide on How to translate a MATLAB file to Python 92 | ==================== 93 | 94 | Note: I haven't tried it, but you may want to try: https://github.com/victorlei/smop for the automatic MATLAB->Python translation 95 | 96 | 1) Use libermate for making a quick automatic translation 97 | 98 | python libermate.py ~/my_path_to/my_matlab_script.m 99 | 100 | If you have problems check my file: https://github.com/awesomebytes/libermate/blob/master/notes_on_using_libermate.txt 101 | 102 | 2) Correct other errors (many mentioned in notes_on_using_libermate.txt), use http://wiki.scipy.org/NumPy_for_Matlab_Users for helping yourself 103 | 104 | 3) Check little pieces of code executing in MATLAB the same line using https://github.com/awesomebytes/python-mlabwrap Use any of my test files as an example on how to execute code and recover variables (structs and cells have some problems). 105 | 106 | 4) Keep a iPython open to check little doubts (numpy arrays don't behave the same as MATLAB matrices) 107 | 108 | 5) Use some IDE on Python to ease your life looking at how to use functions and correcting coding errors, I recomend Eclipse + PyDev 109 | 110 | Eclipse (Standard 4.3.1 as of writing) http://www.eclipse.org/downloads/ 111 | 112 | PyDev plugin (Instructions on how to install) http://pydev.org/manual_101_install.html 113 | 114 | You may need to update Java, here you have a nice tutorial on that: http://www.webupd8.org/2012/01/install-oracle-java-jdk-7-in-ubuntu-via.html 115 | 116 | -------------------------------------------------------------------------------- /src/stmcb.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Jan 22 20:38 2014 5 | 6 | @author: Sammy Pfeiffer 7 | @email: sammypfeiffer@gmail.com 8 | This file imitates the behaviour of stmcb of MatlabTM 9 | 10 | """ 11 | import numpy as np 12 | from scipy.linalg import solve, lstsq 13 | from scipy.signal import lfilter 14 | from convmtx import convmtx 15 | from prony import prony 16 | 17 | 18 | # def printInfo(name, thing_to_print): 19 | # print name + " is: ", thing_to_print 20 | # print name + " shape is:", thing_to_print.shape 21 | 22 | #def stmcb(x, u_in=None, q=None, p=None, niter=5, a_in=None): # Old definition 23 | #function [b,a] = stmcb_test( x, u_in, q, p, niter, a_in ) # matlab definition 24 | def stmcb(*args): 25 | """From MATLAB: 26 | %STMCB Compute linear model via Steiglitz-McBride iteration 27 | % [B,A] = stmcb(H,NB,NA) finds the coefficients of the system 28 | % B(z)/A(z) with approximate impulse response H, NA poles and 29 | % NB zeros. 30 | % 31 | % [B,A] = stmcb(H,NB,NA,N) uses N iterations. N defaults to 5. 32 | % 33 | % [B,A] = stmcb(H,NB,NA,N,Ai) uses the vector Ai as the initial 34 | % guess at the denominator coefficients. If you don't specify Ai, 35 | % STMCB uses [B,Ai] = PRONY(H,0,NA) as the initial conditions. 36 | % 37 | % [B,A] = STMCB(Y,X,NB,NA,N,Ai) finds the system coefficients B and 38 | % A of the system which, given X as input, has Y as output. N and Ai 39 | % are again optional with default values of N = 5, [B,Ai] = PRONY(Y,0,NA). 40 | % Y and X must be the same length. 41 | """ 42 | 43 | # Local Variables: T_sub2, T_sub1, T_minus, C2, C1, a_in, N, u_in, T, a, niter, c, b, i, q, p, u, v, x, T_left, T_right, C1_minus 44 | # Function calls: convmtx, filter, prony, nargchk, stmcb, nargin, length, zeros, error, message, size 45 | #%STMCB Compute linear model via Steiglitz-McBride iteration 46 | #% [B,A] = stmcb(H,NB,NA) finds the coefficients of the system 47 | #% B(z)/A(z) with approximate impulse response H, NA poles and 48 | #% NB zeros. 49 | #% 50 | #% [B,A] = stmcb(H,NB,NA,N) uses N iterations. N defaults to 5. 51 | #% 52 | #% [B,A] = stmcb(H,NB,NA,N,Ai) uses the vector Ai as the initial 53 | #% guess at the denominator coefficients. If you don't specify Ai, 54 | #% STMCB uses [B,Ai] = PRONY(H,0,NA) as the initial conditions. 55 | #% 56 | #% [B,A] = STMCB(Y,X,NB,NA,N,Ai) finds the system coefficients B and 57 | #% A of the system which, given X as input, has Y as output. N and Ai 58 | #% are again optional with default values of N = 5, [B,Ai] = PRONY(Y,0,NA). 59 | #% Y and X must be the same length. 60 | #% 61 | #% % Example: 62 | #% % Approximate the impulse response of a Butterworth filter with a 63 | #% % system of lower order. 64 | #% 65 | #% [b,a] = butter(6,0.2); % Butterworth filter design 66 | #% h = filter(b,a,[1 zeros(1,100)]); % Filter data using above filter 67 | #% freqz(b,a,128) % Frequency response 68 | #% [bb,aa] = stmcb(h,4,4); 69 | #% figure; freqz(bb,aa,128) 70 | #% 71 | #% See also PRONY, LEVINSON, LPC, ARYULE. 72 | #% Author(s): Jim McClellan, 2-89 73 | #% T. Krauss, 4-22-93, new help and options 74 | #% Copyright 1988-2004 The MathWorks, Inc. 75 | #% $Revision: 1.8.4.6 $ $Date: 2012/10/29 19:32:10 $ 76 | #matcompat.error(nargchk(3, 6, nargin, 'struct')) 77 | x = args[0] 78 | # Default assignments 79 | u_in = args[1] 80 | q = args[2] 81 | if len(args) >= 4: 82 | p = args[3] 83 | if type(u_in) == type(1): 84 | if len(args) == 3: 85 | niter = 5 86 | p = args[2] 87 | q = args[1] 88 | [a_in, tmp] = prony(x, 0, p) # In Python there is no way to just get one of the two items returned 89 | 90 | elif len(args) == 4: 91 | niter = args[3] 92 | p = args[2] 93 | q = u_in 94 | [a_in, tmp] = prony(x, 0, p) 95 | 96 | elif len(args) == 5: 97 | a_in = args[4] 98 | niter = args[3] 99 | p = args[2] 100 | q = u_in 101 | 102 | u_in = np.zeros(len(x)) 103 | u_in[0] = 1. 104 | #% make a unit impulse whose length is same as x 105 | else: 106 | if len(u_in) != len(x): 107 | print "stmcb:" 108 | print "Invalid dimensions on u_in and x, must be of the same size: " + str(len(u_in)) + "!=" + str(len(x)) 109 | exit(0) 110 | 111 | if len(args) < 6: 112 | [b, a_in] = prony(x, 0, args[3]) 113 | 114 | if len(args) < 5: 115 | niter = 5 116 | 117 | 118 | a = a_in 119 | N = len(x) 120 | for i in range(niter): 121 | u = lfilter([1], a, x) 122 | v = lfilter([1], a, u_in) 123 | C1 = convmtx(u, (p+1)) 124 | C2 = convmtx(v, (q+1)) 125 | T_left = -C1[0:N,:] 126 | T_right = C2[0:N,:] 127 | T = np.hstack((T_left, T_right)) 128 | #%T = [ C1_minus(1:N,:) C2(1:N,:) ]; 129 | T_minus = -T 130 | T_left = T[:,1:p+q+2] 131 | T_right = T_minus[:,0] 132 | # If not squared matrix: numpy.linalg.lstsq 133 | # If squared matrix: numpy.linalg.solve 134 | if T.shape[0] != T.shape[1]: 135 | [c, residuals, rank, singular_values] = lstsq(T_left, T_right) # lstsq in python returns more stuff 136 | else: 137 | c = solve(T_left, T_right) 138 | #% c = T(:,2:p+q+2)\(T_minus(:,1)); % move 1st column to RHS and do least-squares 139 | a_left = np.array([1]) 140 | a_right = c[:p] 141 | a = np.hstack((a_left, a_right)) 142 | #% denominator coefficients 143 | b = c[p:p+q+1] 144 | #% numerator coefficients 145 | a = a.T 146 | b = b.T 147 | return [b, a] -------------------------------------------------------------------------------- /src/convmtx.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Jan 22 21:38 2014 5 | 6 | @author: Sammy Pfeiffer 7 | @email: sammypfeiffer@gmail.com 8 | This file pretends to imitate the behavior of the MATLAB function convmtx 9 | 10 | """ 11 | 12 | import numpy as np 13 | from scipy.linalg import toeplitz 14 | 15 | def convmtx(v, n): 16 | """From MATLAB: 17 | %CONVMTX Convolution matrix. 18 | % CONVMTX(C,N) returns the convolution matrix for vector C. 19 | % If C is a column vector and X is a column vector of length N, 20 | % then CONVMTX(C,N)*X is the same as CONV(C,X). 21 | % If R is a row vector and X is a row vector of length N, 22 | % then X*CONVMTX(R,N) is the same as CONV(R,X). 23 | """ 24 | # Local Variables: cidx, c, x_left, ridx, m, n, x_right, mv, t, v, x, r, nv 25 | # Function calls: convmtx, length, ones, zeros, size, toeplitz 26 | #%CONVMTX Convolution matrix. 27 | #% CONVMTX(C,N) returns the convolution matrix for vector C. 28 | #% If C is a column vector and X is a column vector of length N, 29 | #% then CONVMTX(C,N)*X is the same as CONV(C,X). 30 | #% If R is a row vector and X is a row vector of length N, 31 | #% then X*CONVMTX(R,N) is the same as CONV(R,X). 32 | #% 33 | #% % Example: 34 | #% % Generate a simple convolution matrix. 35 | #% 36 | #% h = [1 2 3 2 1]; 37 | #% convmtx(h,7) % Convolution matrix 38 | #% 39 | #% See also CONV. 40 | #% Author(s): L. Shure, 47-88 41 | #% T. Krauss, 3-30-93, removed dependence on toeplitz 42 | #% Copyright 1988-2004 The MathWorks, Inc. 43 | #% $Revision: 1.6.4.3 $ $Date: 2012/10/29 19:30:54 $ 44 | try: 45 | [nv, mv] = v.shape # if its vertical, shape will return 2 values, rows and cols 46 | except ValueError: # if its horizontal only len value will be available 47 | mv = len(v) 48 | nv = 1 49 | v = v.flatten(1) 50 | 51 | #c = np.vstack((v, np.zeros(n-1))) 52 | c = np.hstack((v, np.zeros((n-1)))) 53 | r = np.zeros(n) 54 | m = len(c) 55 | x_left = r[n:0:-1] # reverse order from n to 2 in original code 56 | x_right = c.flatten(1) 57 | x = np.hstack((x_left, x_right)) 58 | #%x = [r(n:-1:2) ; c(:)]; % build vector of user data 59 | cidx = np.arange(0., (m-1.)+1).conj().T 60 | ridx = np.arange(n, (1.)+(-1.), -1.) 61 | 62 | t = np.zeros([len(cidx),len(ridx)]) 63 | counter_cidx = 0 64 | for c_val in cidx: 65 | counter_ridx = 0 66 | for r_val in ridx: 67 | t[counter_cidx, counter_ridx] = c_val + r_val 68 | counter_ridx += 1 69 | counter_cidx += 1 70 | #t = cidx[:,int(np.ones(n))-1] + ridx[int(np.ones(m))-1,:] # that double loop should do this... 71 | #% Toeplitz subscripts 72 | 73 | t[:] = x[t.astype(int)-1] 74 | #% actual data 75 | #% end of toeplitz code 76 | 77 | if mv> h = [1 2 3 2 1]; 145 | # >> convmtx(h,7) 146 | # 147 | # ans = 148 | # 149 | # 1 2 3 2 1 0 0 0 0 0 0 150 | # 0 1 2 3 2 1 0 0 0 0 0 151 | # 0 0 1 2 3 2 1 0 0 0 0 152 | # 0 0 0 1 2 3 2 1 0 0 0 153 | # 0 0 0 0 1 2 3 2 1 0 0 154 | # 0 0 0 0 0 1 2 3 2 1 0 155 | # 0 0 0 0 0 0 1 2 3 2 1 156 | ## PYTHON OUTPUT: 157 | # array([[ 1., 2., 3., 2., 1., 0., 0., 0., 0., 0., 0.], 158 | # [ 0., 1., 2., 3., 2., 1., 0., 0., 0., 0., 0.], 159 | # [ 0., 0., 1., 2., 3., 2., 1., 0., 0., 0., 0.], 160 | # [ 0., 0., 0., 1., 2., 3., 2., 1., 0., 0., 0.], 161 | # [ 0., 0., 0., 0., 1., 2., 3., 2., 1., 0., 0.], 162 | 163 | 164 | 165 | if __name__ == '__main__': 166 | main() 167 | 168 | -------------------------------------------------------------------------------- /src/arburg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Jan 22 20:38 2014 5 | 6 | @author: Sammy Pfeiffer 7 | @email: sammypfeiffer@gmail.com 8 | This file pretends to imitate the behaviour of the MATLAB function arburg 9 | 10 | This function can't be tested as the main MATLAB functions isn't even working, 11 | gives: 12 | 13 | Undefined function 'chkinputdatatype' for input arguments of type 'double'. 14 | 15 | But there is still a python version from which we can get it's functionality 16 | http://thomas-cokelaer.info/software/spectrum/html/user/ref_param.html#spectrum.burg.arburg 17 | 18 | """ 19 | 20 | import spectrum 21 | import numpy as np 22 | 23 | #def arburg(x, p): # original def 24 | def arburg(*args): 25 | """From MATLAB: 26 | 27 | %ARBURG AR parameter estimation via Burg method. 28 | % A = ARBURG(X,ORDER) returns the polynomial A corresponding to the AR 29 | % parametric signal model estimate of vector X using Burg's method. 30 | % ORDER is the model order of the AR system. 31 | % 32 | % [A,E] = ARBURG(...) returns the final prediction error E (the variance 33 | % estimate of the white noise input to the AR model). 34 | % 35 | % [A,E,K] = ARBURG(...) returns the vector K of reflection 36 | % coefficients (parcor coefficients). 37 | 38 | Using spectrum arburg: 39 | def arburg(X, order, criteria=None): 40 | Estimate the complex autoregressive parameters by the Burg algorithm. 41 | 42 | .. math:: x(n) = \sqrt{(v}) e(n) + \sum_{k=1}^{P+1} a(k) x(n-k) 43 | 44 | :param x: Array of complex data samples (length N) 45 | :param order: Order of autoregressive process (0= 2: 160 | # varargout.append( E[int(0)-1]) 161 | # 162 | # 163 | # if len(args) >= 3: 164 | # varargout.append( k.flatten(1)) 165 | # 166 | # 167 | # return [varargout] 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /matlab_test_files/invfreqz.m: -------------------------------------------------------------------------------- 1 | function [b,a]=invfreqz(g,w,varargin) 2 | %INVFREQZ Discrete filter least squares fit to frequency response data. 3 | % [B,A] = INVFREQZ(H,W,NB,NA) gives real numerator and denominator 4 | % coefficients B and A of orders NB and NA respectively, where 5 | % H is the desired complex frequency response of the system at frequency 6 | % points W, and W contains the normalized frequency values within the 7 | % interval [0, Pi] (W is in units of radians/sample). 8 | % 9 | % INVFREQZ yields a filter with real coefficients. This means that it is 10 | % sufficient to specify positive frequencies only; the filter fits the data 11 | % conj(H) at -W, ensuring the proper frequency domain symmetry for a real 12 | % filter. 13 | % 14 | % [B,A] = INVFREQZ(H,W,NB,NA,Wt) allows the fit-errors to be weighted 15 | % versus frequency. LENGTH(Wt)=LENGTH(W)=LENGTH(H). 16 | % Determined by minimization of sum |B-H*A|^2*Wt over the freqs in W. 17 | % 18 | % [B,A] = INVFREQZ(H,W,NB,NA,Wt,ITER) does another type of fit: 19 | % Sum |B/A-H|^2*Wt is minimized with respect to the coefficients in B and 20 | % A by numerical search in at most ITER iterations. The A-polynomial is 21 | % then constrained to be stable. [B,A]=INVFREQZ(H,W,NB,NA,Wt,ITER,TOL) 22 | % stops the iterations when the norm of the gradient is less than TOL. 23 | % The default value of TOL is 0.01. The default value of Wt is all ones. 24 | % This default value is also obtained by Wt=[]. 25 | % 26 | % [B,A] = INVFREQZ(H,W,NB,NA,Wt,ITER,TOL,'trace') provides a textual 27 | % progress report of the iteration. 28 | % 29 | % [B,A] = INVFREQZ(H,W,'complex',NB,NA,...) creates a complex filter. In 30 | % this case, no symmetry is enforced and W contains normalized frequency 31 | % values within the interval [-Pi, Pi]. 32 | % 33 | % % Example: 34 | % % Convert a simple transfer function to frequency response data and 35 | % % then back to the original filter coefficients. If the system is 36 | % % unstable, use invfreqs's iterative algorithm to find a stable 37 | % % approximation to the system. 38 | % 39 | % b = [1 2 3 2 3]; % Numerator coefficients 40 | % a = [1 2 3 2 1 4]; % Denominator coefficients 41 | % [h,w] = freqz(b,a,64); 42 | % [bb,aa] = invfreqz(h,w,4,5) % aa has poles in the right half-plane. 43 | % [z,p,k] = tf2zp(bb,aa); % Get Zero-Pole form 44 | % fprintf('Stable Approximation to the system:') 45 | % [bbb,aaa] = invfreqz(h,w,4,5,[],30) % Stable approximation to system 46 | % subplot(2,1,1); zplane(bb,aa); title('PZ plot - Unstable system') 47 | % subplot(2,1,2); zplane(bbb,aaa); title('PZ plot of stable system') 48 | % 49 | % See also FREQZ, FREQS, INVFREQS. 50 | 51 | % Author(s): J.O. Smith and J.N. Little, 4-23-86 52 | % J.N. Little, 4-27-88, revised 53 | % Lennart Ljung, 9-21-92, rewritten 54 | % T. Krauss, 10-19-92, trace mode made optional 55 | % Copyright 1988-2004 The MathWorks, Inc. 56 | % $Revision: 1.8.4.8 $ $Date: 2012/10/29 19:31:23 $ 57 | 58 | % calling sequence is 59 | %function [b,a]=invfreqz(g,w,nb,na,wf,maxiter,tol,pf) 60 | % OR 61 | %function [b,a]=invfreqz(g,w,'complex',nb,na,wf,maxiter,tol,pf) 62 | error(nargchk(4,9,nargin,'struct')) 63 | if ischar(varargin{1}) 64 | realStr = lower(varargin{1}); 65 | varargin(1) = []; 66 | else 67 | realStr = 'real'; 68 | end 69 | gaussFlag = length(varargin)>3; % run Gauss-Newton algorithm or not? 70 | if length(varargin)<6 71 | varargin{6} = []; % pad varargin with []'s 72 | end 73 | [nb,na,wf,maxiter,tol,pf] = deal(varargin{:}); 74 | 75 | switch realStr 76 | case 'real' 77 | realFlag = 1; 78 | case 'complex' 79 | realFlag = 0; 80 | otherwise 81 | warning(message('signal:invfreqz:InvalidParam', realStr)); 82 | realFlag = 0; 83 | end 84 | 85 | nk=0;T=1; % The code is prepared for arbitrary sampling interval T and for 86 | % constraining the numerator to begin with nk zeros. 87 | 88 | nb=nb+nk+1; 89 | if isempty(pf) 90 | verb=0; 91 | elseif (strcmp(pf,'trace')), 92 | verb=1; 93 | else 94 | error(message('signal:invfreqz:NotSupported', pf)); 95 | end 96 | if isempty(wf),wf=ones(length(w),1);end 97 | wf=sqrt(wf); 98 | 99 | if length(g)~=length(w),error(message('signal:invfreqz:InvalidDimensions', 'H', 'W')),end 100 | if length(wf)~=length(w),error(message('signal:invfreqz:InvalidDimensions', 'Wt', 'W')),end 101 | if any( (w>pi) | (w<0) ) && realFlag 102 | warning(message('signal:invfreqz:InvalidRegion', 'W', 'INVFREQZ', '''complex''')) 103 | end 104 | [rw,cw]=size(w); if rw>cw, w=w'; end 105 | [rg,cg]=size(g); if cg>rg, g=g.'; end 106 | [rwf,cwf]=size(wf); if cwf>rwf, wf=wf'; end 107 | 108 | nm=max(na,nb+nk-1); 109 | OM=exp(-1i*(0:nm)'*w*T); 110 | 111 | % 112 | % Estimation in the least squares case: 113 | % 114 | Dva=(OM(2:na+1,:).').*(g*ones(1,na)); 115 | Dvb=-(OM(nk+1:nk+nb,:).'); 116 | D=[Dva Dvb].*(wf*ones(1,na+nb)); 117 | if realFlag 118 | R=real(D'*D); 119 | Vd=real(D'*(-g.*wf)); 120 | else 121 | R=D'*D; 122 | Vd=D'*(-g.*wf); 123 | end 124 | th=R\Vd; 125 | a=[1 th(1:na).'];b=[zeros(1,nk) th(na+1:na+nb).']; 126 | 127 | if ~gaussFlag,return,end 128 | 129 | % Now for the iterative minimization 130 | if isempty(maxiter), maxiter = 30; end 131 | 132 | if isempty(tol) 133 | tol = 0.01; 134 | end 135 | indb=1:length(b);indg=1:length(a); 136 | a=polystab(a); % Stabilizing the denominator 137 | 138 | % The initial estimate: 139 | 140 | GC=((b*OM(indb,:))./(a*OM(indg,:))).'; 141 | e=(GC-g).*wf; 142 | Vcap=e'*e; t=[a(2:na+1) b(nk+1:nk+nb)].'; 143 | if (verb), 144 | %messages similar to invfreqs 145 | clc, disp([' ' getString(message('signal:invfreqs:INITIALESTIMATE'))]); 146 | disp([getString(message('signal:invfreqs:CurrentFit')) ' ' num2str(Vcap)]) 147 | disp(getString(message('signal:invfreqs:Parvector'))); 148 | disp(t) 149 | end; 150 | 151 | % 152 | % ** the minimization loop ** 153 | % 154 | gndir=2*tol+1;l=0;st=0; 155 | while all([norm(gndir)>tol l Vcap ll<20]) 180 | 181 | t1=t-k*gndir; if ll==19,t1=t;end 182 | a=polystab([1 t1(1:na).']); 183 | t1(1:na)=a(2:na+1).'; %Stabilizing denominator 184 | b=[zeros(1,nk) t1(na+1:na+nb).']; 185 | GC=((b*OM(indb,:))./(a*OM(indg,:))).'; 186 | V1=((GC-g).*wf)'*((GC-g).*wf); t1=[a(2:na+1) b(nk+1:nk+nb)].'; 187 | if (verb), 188 | home, disp(int2str(ll)) 189 | end; 190 | k=k/2; 191 | ll=ll+1; if ll==20, st=1;end 192 | if ll==10,gndir=Vd/norm(R)*length(R);k=1;end 193 | end 194 | 195 | if (verb), 196 | home 197 | disp([' ' getString(message('signal:invfreqs:ITERATION')) ' ' int2str(l)]) 198 | disp([getString(message('signal:invfreqs:CurrentFit')) ' ' num2str(V1) ' ' getString(message('signal:invfreqs:PreviousFit')) ' ' num2str(Vcap)]) 199 | disp(getString(message('signal:invfreqs:CurrentParPrevparGNdir'))); 200 | disp([t1 t gndir]) 201 | disp([getString(message('signal:invfreqs:NormOfGNvector')) ' ' num2str(norm(gndir))]) 202 | if st==1, 203 | disp(getString(message('signal:invfreqs:NoImprovement'))), 204 | disp(getString(message('signal:invfreqs:IterationsThereforeTerminated'))), 205 | end 206 | end 207 | t=t1; Vcap=V1; 208 | end 209 | -------------------------------------------------------------------------------- /matlab_test_files/invfreqz_test.m: -------------------------------------------------------------------------------- 1 | function [b,a]=invfreqz(g,w,varargin) 2 | %INVFREQZ Discrete filter least squares fit to frequency response data. 3 | % [B,A] = INVFREQZ(H,W,NB,NA) gives real numerator and denominator 4 | % coefficients B and A of orders NB and NA respectively, where 5 | % H is the desired complex frequency response of the system at frequency 6 | % points W, and W contains the normalized frequency values within the 7 | % interval [0, Pi] (W is in units of radians/sample). 8 | % 9 | % INVFREQZ yields a filter with real coefficients. This means that it is 10 | % sufficient to specify positive frequencies only; the filter fits the data 11 | % conj(H) at -W, ensuring the proper frequency domain symmetry for a real 12 | % filter. 13 | % 14 | % [B,A] = INVFREQZ(H,W,NB,NA,Wt) allows the fit-errors to be weighted 15 | % versus frequency. LENGTH(Wt)=LENGTH(W)=LENGTH(H). 16 | % Determined by minimization of sum |B-H*A|^2*Wt over the freqs in W. 17 | % 18 | % [B,A] = INVFREQZ(H,W,NB,NA,Wt,ITER) does another type of fit: 19 | % Sum |B/A-H|^2*Wt is minimized with respect to the coefficients in B and 20 | % A by numerical search in at most ITER iterations. The A-polynomial is 21 | % then constrained to be stable. [B,A]=INVFREQZ(H,W,NB,NA,Wt,ITER,TOL) 22 | % stops the iterations when the norm of the gradient is less than TOL. 23 | % The default value of TOL is 0.01. The default value of Wt is all ones. 24 | % This default value is also obtained by Wt=[]. 25 | % 26 | % [B,A] = INVFREQZ(H,W,NB,NA,Wt,ITER,TOL,'trace') provides a textual 27 | % progress report of the iteration. 28 | % 29 | % [B,A] = INVFREQZ(H,W,'complex',NB,NA,...) creates a complex filter. In 30 | % this case, no symmetry is enforced and W contains normalized frequency 31 | % values within the interval [-Pi, Pi]. 32 | % 33 | % % Example: 34 | % % Convert a simple transfer function to frequency response data and 35 | % % then back to the original filter coefficients. If the system is 36 | % % unstable, use invfreqs's iterative algorithm to find a stable 37 | % % approximation to the system. 38 | % 39 | % b = [1 2 3 2 3]; % Numerator coefficients 40 | % a = [1 2 3 2 1 4]; % Denominator coefficients 41 | % [h,w] = freqz(b,a,64); 42 | % [bb,aa] = invfreqz(h,w,4,5) % aa has poles in the right half-plane. 43 | % [z,p,k] = tf2zp(bb,aa); % Get Zero-Pole form 44 | % fprintf('Stable Approximation to the system:') 45 | % [bbb,aaa] = invfreqz(h,w,4,5,[],30) % Stable approximation to system 46 | % subplot(2,1,1); zplane(bb,aa); title('PZ plot - Unstable system') 47 | % subplot(2,1,2); zplane(bbb,aaa); title('PZ plot of stable system') 48 | % 49 | % See also FREQZ, FREQS, INVFREQS. 50 | 51 | % Author(s): J.O. Smith and J.N. Little, 4-23-86 52 | % J.N. Little, 4-27-88, revised 53 | % Lennart Ljung, 9-21-92, rewritten 54 | % T. Krauss, 10-19-92, trace mode made optional 55 | % Copyright 1988-2004 The MathWorks, Inc. 56 | % $Revision: 1.8.4.8 $ $Date: 2012/10/29 19:31:23 $ 57 | 58 | % calling sequence is 59 | %function [b,a]=invfreqz(g,w,nb,na,wf,maxiter,tol,pf) 60 | % OR 61 | %function [b,a]=invfreqz(g,w,'complex',nb,na,wf,maxiter,tol,pf) 62 | error(nargchk(4,9,nargin,'struct')) 63 | if ischar(varargin{1}) 64 | realStr = lower(varargin{1}); 65 | varargin(1) = []; 66 | else 67 | realStr = 'real'; 68 | end 69 | gaussFlag = length(varargin)>3; % run Gauss-Newton algorithm or not? 70 | if length(varargin)<6 71 | varargin{6} = []; % pad varargin with []'s 72 | end 73 | [nb,na,wf,maxiter,tol,pf] = deal(varargin{:}); 74 | 75 | switch realStr 76 | case 'real' 77 | realFlag = 1; 78 | case 'complex' 79 | realFlag = 0; 80 | otherwise 81 | warning(message('signal:invfreqz:InvalidParam', realStr)); 82 | realFlag = 0; 83 | end 84 | 85 | nk=0;T=1; % The code is prepared for arbitrary sampling interval T and for 86 | % constraining the numerator to begin with nk zeros. 87 | 88 | nb=nb+nk+1; 89 | if isempty(pf) 90 | verb=0; 91 | elseif (strcmp(pf,'trace')), 92 | verb=1; 93 | else 94 | error(message('signal:invfreqz:NotSupported', pf)); 95 | end 96 | if isempty(wf),wf=ones(length(w),1);end 97 | wf=sqrt(wf); 98 | 99 | if length(g)~=length(w),error(message('signal:invfreqz:InvalidDimensions', 'H', 'W')),end 100 | if length(wf)~=length(w),error(message('signal:invfreqz:InvalidDimensions', 'Wt', 'W')),end 101 | % if any( (w>pi) | (w<0) ) && realFlag 102 | % warning(message('signal:invfreqz:InvalidRegion', 'W', 'INVFREQZ', '''complex''')) 103 | % end 104 | [rw,cw]=size(w); if rw>cw, w=w'; end 105 | [rg,cg]=size(g); if cg>rg, g=g.'; end 106 | [rwf,cwf]=size(wf); if cwf>rwf, wf=wf'; end 107 | 108 | nm=max(na,nb+nk-1); 109 | OM=exp(-1i*(0:nm)'*w*T); 110 | 111 | % 112 | % Estimation in the least squares case: 113 | % 114 | Dva=(OM(2:na+1,:).').*(g*ones(1,na)); 115 | Dvb=-(OM(nk+1:nk+nb,:).'); 116 | D=[Dva Dvb].*(wf*ones(1,na+nb)); 117 | if realFlag 118 | R=real(D'*D); 119 | Vd=real(D'*(-g.*wf)); 120 | else 121 | R=D'*D; 122 | Vd=D'*(-g.*wf); 123 | end 124 | th=R\Vd; 125 | a=[1 th(1:na).'];b=[zeros(1,nk) th(na+1:na+nb).']; 126 | 127 | if ~gaussFlag,return,end 128 | 129 | % Now for the iterative minimization 130 | if isempty(maxiter), maxiter = 30; end 131 | 132 | if isempty(tol) 133 | tol = 0.01; 134 | end 135 | indb=1:length(b);indg=1:length(a); 136 | a=polystab(a); % Stabilizing the denominator 137 | 138 | % The initial estimate: 139 | 140 | GC=((b*OM(indb,:))./(a*OM(indg,:))).'; 141 | e=(GC-g).*wf; 142 | Vcap=e'*e; t=[a(2:na+1) b(nk+1:nk+nb)].'; 143 | if (verb), 144 | %messages similar to invfreqs 145 | clc, disp([' ' getString(message('signal:invfreqs:INITIALESTIMATE'))]); 146 | disp([getString(message('signal:invfreqs:CurrentFit')) ' ' num2str(Vcap)]) 147 | disp(getString(message('signal:invfreqs:Parvector'))); 148 | disp(t) 149 | end; 150 | 151 | % 152 | % ** the minimization loop ** 153 | % 154 | gndir=2*tol+1;l=0;st=0; 155 | while all([norm(gndir)>tol l Vcap ll<20]) 180 | 181 | t1=t-k*gndir; if ll==19,t1=t;end 182 | a=polystab([1 t1(1:na).']); 183 | t1(1:na)=a(2:na+1).'; %Stabilizing denominator 184 | b=[zeros(1,nk) t1(na+1:na+nb).']; 185 | GC=((b*OM(indb,:))./(a*OM(indg,:))).'; 186 | V1=((GC-g).*wf)'*((GC-g).*wf); t1=[a(2:na+1) b(nk+1:nk+nb)].'; 187 | if (verb), 188 | home, disp(int2str(ll)) 189 | end; 190 | k=k/2; 191 | ll=ll+1; if ll==20, st=1;end 192 | if ll==10,gndir=Vd/norm(R)*length(R);k=1;end 193 | end 194 | 195 | if (verb), 196 | home 197 | disp([' ' getString(message('signal:invfreqs:ITERATION')) ' ' int2str(l)]) 198 | disp([getString(message('signal:invfreqs:CurrentFit')) ' ' num2str(V1) ' ' getString(message('signal:invfreqs:PreviousFit')) ' ' num2str(Vcap)]) 199 | disp(getString(message('signal:invfreqs:CurrentParPrevparGNdir'))); 200 | disp([t1 t gndir]) 201 | disp([getString(message('signal:invfreqs:NormOfGNvector')) ' ' num2str(norm(gndir))]) 202 | if st==1, 203 | disp(getString(message('signal:invfreqs:NoImprovement'))), 204 | disp(getString(message('signal:invfreqs:IterationsThereforeTerminated'))), 205 | end 206 | end 207 | t=t1; Vcap=V1; 208 | end 209 | -------------------------------------------------------------------------------- /matlab_test_files/invfreqs.m: -------------------------------------------------------------------------------- 1 | function [b,a]=invfreqs(g,w,varargin) 2 | %INVFREQS Analog filter least squares fit to frequency response data. 3 | % [B,A] = INVFREQS(H,W,nb,na) gives real numerator and denominator 4 | % coefficients B and A of orders nb and na respectively, where 5 | % H is the desired complex frequency response of the system at frequency 6 | % points W, and W contains the frequency values in radians/s. 7 | % INVFREQS yields a filter with real coefficients. This means that it is 8 | % sufficient to specify positive frequencies only; the filter fits the data 9 | % conj(H) at -W, ensuring the proper frequency domain symmetry for a real 10 | % filter. 11 | % 12 | % [B,A]=INVFREQS(H,W,nb,na,Wt) allows the fit-errors to the weighted 13 | % versus frequency. LENGTH(Wt)=LENGTH(W)=LENGTH(H). 14 | % Determined by minimization of sum |B-H*A|^2*Wt over the freqs in W. 15 | % 16 | % [B,A] = INVFREQS(H,W,nb,na,Wt,ITER) does another type of fit: 17 | % Sum |B/A-H|^2*Wt is minimized with respect to the coefficients in B and 18 | % A by numerical search in at most ITER iterations. The A-polynomial is 19 | % then constrained to be stable. [B,A]=INVFREQS(H,W,nb,na,Wt,ITER,TOL) 20 | % stops the iterations when the norm of the gradient is less than TOL. 21 | % The default value of TOL is 0.01. The default value of Wt is all ones. 22 | % This default value is also obtained by Wt=[]. 23 | % 24 | % [B,A]=INVFREQS(H,W,nb,na,Wt,ITER,TOL,'trace') provides a textual 25 | % progress report of the iteration. 26 | % 27 | % [B,A] = INVFREQS(H,W,'complex',NB,NA,...) creates a complex filter. In 28 | % this case, no symmetry is enforced. 29 | % 30 | % % Example: 31 | % % Convert a simple transfer function to frequency response data and 32 | % % then back to the original filter coefficients. If the system is 33 | % % unstable, use invfreqs's iterative algorithm to find a stable 34 | % % approximation to the system. 35 | % 36 | % b = [1 2 3 2 3]; % Numerator coefficients 37 | % a = [1 2 3 2 1 4]; % Denominator coefficients 38 | % [h,w] = freqs(b,a,64); 39 | % [bb,aa] = invfreqs(h,w,4,5) % aa has poles in the right half-plane. 40 | % fprintf('Stable Approximation to the system:') 41 | % [bbb,aaa] = invfreqs(h,w,4,5,[],30) % stable approximation to system 42 | % 43 | % See also FREQZ, FREQS, INVFREQZ. 44 | 45 | % Author(s): J.O. Smith and J.N. Little, 4-23-86 46 | % J.N. Little, 4-27-88, revised 47 | % Lennart Ljung, 9-21-92, rewritten 48 | % T. Krauss, 10-22-92, trace mode made optional 49 | % Copyright 1988-2011 The MathWorks, Inc. 50 | % 51 | 52 | % calling sequence is 53 | %function [b,a]=invfreqs(g,w,nb,na,wf,maxiter,tol,pf) 54 | % OR 55 | %function [b,a]=invfreqs(g,w,'complex',nb,na,wf,maxiter,tol,pf) 56 | error(nargchk(4,9,nargin,'struct')) 57 | if ischar(varargin{1}) 58 | realStr = lower(varargin{1}); 59 | varargin(1) = []; 60 | else 61 | realStr = 'real'; 62 | end 63 | gaussFlag = length(varargin)>3; % run Gauss-Newton algorithm or not? 64 | if length(varargin)<6 65 | varargin{6} = []; % pad varargin with []'s 66 | end 67 | [nb,na,wf,maxiter,tol,pf] = deal(varargin{:}); 68 | 69 | switch realStr 70 | case 'real' 71 | realFlag = 1; 72 | case 'complex' 73 | realFlag = 0; 74 | otherwise 75 | warning(message('signal:invfreqs:InvalidParam', realStr)); 76 | realFlag = 0; 77 | end 78 | 79 | nk=0; % The code is prepared for constraining the numerator to 80 | % begin with nk zeros. 81 | 82 | nb=nb+nk+1; 83 | if isempty(pf) 84 | verb=0; 85 | elseif (strcmp(pf,'trace')), 86 | verb=1; 87 | else 88 | error(message('signal:invfreqs:NotSupported', pf)); 89 | end 90 | if isempty(wf),wf=ones(length(w),1);end 91 | wf=sqrt(wf); 92 | 93 | if length(g)~=length(w) 94 | error(message('signal:invfreqs:UnmatchedLengths', 'H', 'W')) 95 | end 96 | 97 | if length(wf)~=length(w) 98 | error(message('signal:invfreqs:UnmatchedLengths', 'Wt', 'W')) 99 | end 100 | 101 | if any( w(:)<0 ) && realFlag 102 | warning(message('signal:invfreqs:InvalidWParam', 'W', 'INVFREQS', 'complex')) 103 | end 104 | 105 | [rw,cw]=size(w); if rw>cw, w=w'; end 106 | [rg,cg]=size(g); if cg>rg, g=g.'; end 107 | [rwf,cwf]=size(wf); if cwf>rwf, wf=wf'; end 108 | 109 | nm=max(na+1,nb+nk); 110 | indb=nb:-1:1; indg=na+1:-1:1; inda=na:-1:1; 111 | 112 | OM=ones(1,length(w)); 113 | for kom=1:nm-1 114 | OM=[OM;(1i*w).^kom]; 115 | end 116 | 117 | % 118 | % Estimation in the least squares case: 119 | % 120 | Dva=(OM(inda,:).').*(g*ones(1,na)); 121 | Dvb=-(OM(indb,:).'); 122 | D=[Dva Dvb].*(wf*ones(1,na+nb)); 123 | R=D'*D; 124 | Vd=D'*((-g.*OM(na+1,:).').*wf); 125 | if realFlag 126 | R=real(R); 127 | Vd=real(Vd); 128 | end 129 | th=R\Vd; 130 | a=[1 th(1:na).'];b=[zeros(1,nk) th(na+1:na+nb).']; 131 | 132 | if ~gaussFlag,return,end 133 | 134 | % Now for the iterative minimization 135 | 136 | if isempty(maxiter), maxiter = 30; end 137 | if isempty(tol) 138 | tol=0.01; 139 | end 140 | % Stabilizing the denominator: 141 | a=apolystab(a,realFlag); 142 | 143 | % The initial estimate: 144 | 145 | GC=((b*OM(indb,:))./(a*OM(indg,:))).'; 146 | e=(GC-g).*wf; 147 | Vcap=e'*e; t=[a(2:na+1) b(nk+1:nk+nb)].'; 148 | if (verb), 149 | % invfreqz using same messages 150 | clc, disp([' ' getString(message('signal:invfreqs:INITIALESTIMATE'))]); 151 | disp([getString(message('signal:invfreqs:CurrentFit')) ' ' num2str(Vcap)]) 152 | disp(getString(message('signal:invfreqs:Parvector'))); 153 | disp(t) 154 | end 155 | 156 | % 157 | % ** the minimization loop ** 158 | % 159 | gndir=2*tol+1;l=0;st=0; 160 | while all([norm(gndir)>tol l Vcap ll<20]), 184 | 185 | t1=t-k*gndir; if ll==19,t1=t;end 186 | a=[1 t1(1:na).']; 187 | b=[zeros(1,nk) t1(na+1:na+nb).']; 188 | a=apolystab(a,realFlag); % Stabilizing the denominator 189 | t1(1:na)=a(2:na+1).'; 190 | GC=((b*OM(indb,:))./(a*OM(indg,:))).'; 191 | V1=((GC-g).*wf)'*((GC-g).*wf); 192 | if (verb), 193 | home, disp(int2str(ll)) 194 | end; 195 | k=k/2; 196 | ll=ll+1; if ll==10, gndir=Vd/norm(R)*length(R);k=1;end 197 | if ll==20,st=1;end 198 | end 199 | if (verb), 200 | home 201 | disp([' ' getString(message('signal:invfreqs:ITERATION')) ' ' int2str(l)]) 202 | disp([getString(message('signal:invfreqs:CurrentFit')) ' ' num2str(V1) ' ' getString(message('signal:invfreqs:PreviousFit')) ' ' num2str(Vcap)]) 203 | disp(getString(message('signal:invfreqs:CurrentParPrevparGNdir'))); 204 | disp([t1 t gndir]) 205 | disp([getString(message('signal:invfreqs:NormOfGNvector')) ' ' num2str(norm(gndir))]) 206 | if st==1, 207 | disp(getString(message('signal:invfreqs:NoImprovement'))), 208 | disp(getString(message('signal:invfreqs:IterationsThereforeTerminated'))), 209 | end 210 | end 211 | t=t1; Vcap=V1; 212 | end 213 | 214 | function a = apolystab(a,realFlag) 215 | %APOLYSTAB Stabilize filter, analog 216 | % inputs: a - denominator polynomial 217 | % realFlag - 1 for real, 0 for complex 218 | % returns stabilized denoninator polynomial 219 | if length(a)>0 220 | v=roots(a); 221 | vind=find(real(v)>0); 222 | v(vind)=-v(vind); 223 | a=poly(v); 224 | if realFlag 225 | a=real(a); 226 | end 227 | end 228 | --------------------------------------------------------------------------------