mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
linearPredictor.hpp
Go to the documentation of this file.
1 /** \file linearPredictor.hpp
2  * \brief Working with linear prediction.
3  *
4  * \author Jared R. Males (jaredmales@gmail.com)
5  *
6  * \ingroup signal_processing_files
7  *
8  */
9 
10 //***********************************************************************//
11 // Copyright 2015, 2016, 2017 Jared R. Males (jaredmales@gmail.com)
12 //
13 // This file is part of mxlib.
14 //
15 // mxlib is free software: you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation, either version 3 of the License, or
18 // (at your option) any later version.
19 //
20 // mxlib is distributed in the hope that it will be useful,
21 // but WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 // GNU General Public License for more details.
24 //
25 // You should have received a copy of the GNU General Public License
26 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
27 //***********************************************************************//
28 
29 #ifndef linearPredictor_hpp
30 #define linearPredictor_hpp
31 
32 #include <vector>
33 #include <complex>
34 
35 #include "../math/constants.hpp"
36 #include "../math/eigenLapack.hpp"
37 
38 #include "levinsonRecursion.hpp"
39 
40 namespace mx
41 {
42 namespace sigproc
43 {
44 
45 /// A class to support linear prediction.
46 /** \ingroup signal_processing
47  *
48  * \todo document linearPredictor
49  */
50 template<typename _realT>
52 {
53  typedef _realT realT;
54 
55  Eigen::Array<realT, -1, -1> _c;
56 
57  realT _setCondition {0};
58  realT _actCondition {0};
59  int _nRejected {0};
60 
61  /// Calculate the LP coefficients given an autocorrelation.
62  /** If condition==0 then the levinson recursion is used.
63  * Otherwise, SVD pseudo-inversion is used with the given condition number.
64  */
65  int calcCoefficients( std::vector<realT> & ac,
66  size_t Nc,
67  realT condition = 0,
68  size_t extrap = 0
69  )
70  {
71 
72  if(condition == 0)
73  {
74  return calcCoefficientsLevinson( ac, Nc, extrap );
75  }
76 
77 
78  Eigen::Array<realT,-1,-1> Rmat, Rvec, PInv, LPcoeff;
79 
80  Rmat.resize(Nc, Nc);
81  Rvec.resize(1, Nc);
82 
83  for(size_t i=0; i<Nc; ++i)
84  {
85  for(size_t j=0; j<Nc; ++j)
86  {
87  Rmat(i,j) = ac[ fabs(i-j)];
88  }
89 
90  Rvec(0,i) = ac[i+1];
91  }
92 
93  realT tmpCond = condition;
94 
95  _setCondition = condition;
96  math::eigenPseudoInverse(PInv, tmpCond, _nRejected, Rmat, condition);
97 
98 
99  _actCondition = tmpCond;
100 
101  _c = Rvec.matrix()*PInv.matrix();
102 
103 
104 
105  return 0;
106  }
107 
108  int calcCoefficientsLevinson( std::vector<realT> & ac,
109  size_t Nc,
110  size_t extrap = 0
111  )
112  {
113  std::vector<realT> r, x, y;
114 
115  r.resize(2.*Nc-1);
116  x.resize(Nc);
117  y.resize(Nc);
118 
119  for(size_t i=0; i< Nc; ++i) r[i] = ac[Nc-i - 1];
120  for(size_t i=Nc; i< 2*Nc-1; ++i) r[i] = ac[i-Nc+1];
121 
122  for(size_t i=0;i<Nc; ++i) y[i] = ac[i+1];
123 
124  levinsonRecursion(r.data(), x.data(), y.data(), Nc);
125 
126  _c.resize(1, Nc);
127  for(size_t i=0; i< Nc; ++i) _c(0,i) = x[i];
128 
129 
130  if(extrap == 1)
131  {
132  Eigen::Array<realT, -1, -1> ex(_c.rows(), _c.cols());
133  for(size_t j=0; j < extrap; ++j)
134  {
135  for(size_t i=0; i< Nc-1; ++i)
136  {
137  ex(0,i) = _c(0,0)*_c(0,i) + _c(0,i+1);
138  }
139  ex(0,Nc-1) = _c(0,0)*_c(0,Nc-1);
140 
141  _c = ex;
142  }
143  }
144 
145 
146 
147  return 0;
148  }
149 
150  realT c(size_t i)
151  {
152  return _c(0,i);
153  }
154 
155  realT predict( std::vector<realT> & hist,
156  int idx )
157  {
158  realT x = 0;
159 
160  if(idx < _c.cols()) return 0;
161 
162  for(int i=0; i< _c.cols(); ++i)
163  {
164  x += _c(0,i)*hist[idx-i];
165  }
166 
167  return x;
168  }
169 
170  realT spectralResponse( realT f, realT fs)
171  {
172  int n = _c.cols();
173 
174  std::complex<realT> He = 0;
175  for(int j=0; j < n; ++j)
176  {
177  realT s = (j+1.0)* math::two_pi<realT>();
178  He += _c(0,j) * exp(s*std::complex<realT>(0,-1.0)*f/fs);
179  }
180 
181  realT one = 1.0;
182  return std::norm( one/ (one - He));
183  }
184 
185 };
186 
187 } //namespace sigproc
188 } //namespace mx
189 #endif //linearPredictor_hpp
190 
int eigenPseudoInverse(Eigen::Array< dataT, -1, -1 > &PInv, dataT &condition, int &nRejected, Eigen::Array< dataT, -1, -1 > &U, Eigen::Array< dataT, -1, -1 > &S, Eigen::Array< dataT, -1, -1 > &VT, Eigen::Array< dataT, -1, -1 > &A, dataT &maxCondition, dataT alpha=0, int interact=MX_PINV_NO_INTERACT)
Calculate the pseudo-inverse of a patrix using the SVD.
The mxlib c++ namespace.
Definition: mxError.hpp:107
A class to support linear prediction.
int calcCoefficients(std::vector< realT > &ac, size_t Nc, realT condition=0, size_t extrap=0)
Calculate the LP coefficients given an autocorrelation.