mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
clAOLinearPredictor.hpp
Go to the documentation of this file.
1 /** \file clAOLinearPredictor.hpp
2  * \author Jared R. Males (jaredmales@gmail.com)
3  * \brief Provides a class to manage closed loop gain linear predictor determination.
4  * \ingroup mxAO_files
5  *
6  */
7 
8 #ifndef clAOLinearPredictor_hpp
9 #define clAOLinearPredictor_hpp
10 
11 #include <vector>
12 
13 #include "../../math/geo.hpp"
14 
15 #include "../../sigproc/psdUtils.hpp"
16 
17 #include "../../sigproc/autocorrelation.hpp"
18 #include "../../sigproc/linearPredictor.hpp"
19 
20 #include "clGainOpt.hpp"
21 
22 namespace mx
23 {
24 namespace AO
25 {
26 namespace analysis
27 {
28 
29 ///Class to manage the calculation of linear predictor coefficients for a closed-loop AO system.
30 /**
31  * \tparam _realT the real floating point type in which to do all arithmetic.
32  *
33  * \ingroup mxAOAnalytic
34  */
35 template<typename _realT>
37 {
38  typedef _realT realT;
39 
40  std::vector<realT> PSDtn;
41 
42  std::vector<realT> psd2s;
43 
44  std::vector<realT> ac;
45 
47 
49 
50  realT m_min_var0 {0};
51  realT m_min_sc0 {10};
52  realT m_precision0 {10};
53  realT m_max_sc0 {100};
54  realT m_dPrecision {3};
55 
56  realT m_gmax_lp {5}; ///< The maximum allowable gain for LP.
57 
58  //Stopping conditions:
59  realT m_minPrecision {0.001};
60  int m_maxIts {100};
61 
62  int extrap;
63 
64  clAOLinearPredictor()
65  {
66  extrap = 0;
67  }
68 
69  ///Calculate the LP coefficients for a turbulence PSD and a noise PSD.
70  /** This combines the two PSDs, augments to two-sided, and calls the linearPredictor.calcCoefficients method.
71  *
72  * A regularization constant can be added to the PSD as well.
73  *
74  */
75  int calcCoefficients( std::vector<realT> & PSDt, ///< [in] the turbulence PSD
76  std::vector<realT> & PSDn, ///< [in] the WFS noise PSD
77  realT PSDreg, ///< [in] the regularizing constant. Set to 0 to not use.
78  int Nc, ///< [in] the number of LP coefficients.
79  realT condition = 0
80  )
81  {
82  PSDtn.resize(PSDt.size());
83 
84  for(size_t i=0; i< PSDt.size(); ++i)
85  {
86  PSDtn[i] = PSDt[i] + PSDn[i] + PSDreg;
87  }
88 
89  sigproc::augment1SidedPSD( psd2s, PSDtn,1);
90 
91  ac.resize(psd2s.size());
92 
93  //#pragma omp critical
94  acpsd(ac, psd2s);
95 
96  return lp.calcCoefficients(ac, Nc, condition, extrap);
97  }
98 
99 
100  ///Worker function for regularizing the PSD for coefficient calculation.
101  /**
102  * \tparam printout if true then the results are printed to stdout as they are calculated.
103  *
104  * On first call (min_var = 0):
105  * loop over scale factors from min_sc to max_sc (<=) in steps of precision.
106  *
107  * On subsequent calls, when min_var and min_sc are passed back in
108  * loop over scale factors from min_sc-precision to max_sc in steps of
109  */
110  template< bool printout=false>
111  int _regularizeCoefficients( realT & min_var, ///< [in.out] the minimum variance found. Set to 0 on initial call
112  realT & min_sc, ///< [in.out] the scale factor at the minimum variance.
113  realT precision, ///< [in] the step-size for the scale factor
114  realT max_sc, ///< [in] the maximum scale factor to test
115  clGainOpt<realT> & go_lp, ///< [in] the gain optimization object
116  std::vector<realT> & PSDt, ///< [in] the turbulence PSD
117  std::vector<realT> & PSDn, ///< [in] the WFS noise PSD
118  int Nc ///< [in] the number of coefficients
119  )
120  {
121  realT gmax_lp;
122  realT gopt_lp;
123  realT var_lp;
124 
125  realT sc0;
126 
127  realT last_var;
128 
129 
130 
131  //min_var == 0 indicates first call
132  if( min_var == 0)
133  {
134  sc0 = min_sc;
135  min_var = std::numeric_limits<realT>::max();
136  last_var = std::numeric_limits<realT>::max();
137  }
138  else
139  {
140  sc0 = min_sc - precision*m_dPrecision;
141  //sc0 = min_sc;
142  last_var = min_var;
143  }
144 
145  //auto it = std::max_element(std::begin(PSDt), std::end(PSDt));
146  realT psdReg = PSDt[0];//*it/10;
147 
148  //Test from sc0 to max_sc in steps of precision
149  for(realT sc = sc0; sc <= max_sc; sc += precision)
150  {
151  if( calcCoefficients(PSDt, PSDn, psdReg*pow(10, -sc/10), Nc) < 0) return -1;
152 
153  go_lp.a(lp._c);
154  go_lp.b(lp._c);
155 
156  realT ll = 0, ul = 0;
157  gmax_lp = go_lp.maxStableGain(ll,ul);
158  if(gmax_lp> m_gmax_lp) gmax_lp = m_gmax_lp;
159  gopt_lp = go_lp.optGainOpenLoop(var_lp, PSDt, PSDn, gmax_lp);
160 
161  if(printout)
162  {
163  std::cout << -(sc)/10 << " " << gmax_lp << " " << gopt_lp << " " << var_lp << "\n";
164  }
165 
166  if( var_lp < min_var )
167  {
168  min_var = var_lp;
169  min_sc = sc;
170  }
171 
172  //A jump by a factor of 10 indicates the wall
173  if( var_lp/last_var > 10 ) return 0;
174 
175  last_var = var_lp;
176  }
177 
178  return -1;
179 
180  }
181 
182  /// Regularize the PSD and calculate the associated LP coefficients.
183  /** The PSD is regularized by adding a constant to it. This constant is found by minimizing the variance of the residual PSD.
184  *
185  * \tparam printout if true then the results are printed to stdout as they are calculated.
186  */
187  template< bool printout=false>
188  int regularizeCoefficients( realT & gmax_lp, ///< [out] the maximum gain calculated for the regularized PSD
189  realT & gopt_lp, ///< [out] the optimum gain calculated for the regularized PSD
190  realT & var_lp, ///< [out] the variance at the optimum gain.
191  clGainOpt<realT> & go_lp, ///< [in] the gain optimization object
192  std::vector<realT> & PSDt, ///< [in] the turbulence PSD
193  std::vector<realT> & PSDn, ///< [in] the WFS noise PSD
194  int Nc ///< [in] the number of coefficients
195  )
196  {
197 
198  realT min_var = m_min_var0;
199  realT min_sc = m_min_sc0;
200  realT precision = m_precision0;
201  realT max_sc = m_max_sc0;
202 
203 
204  int its = 0;
205  while(precision > m_minPrecision && its < m_maxIts)
206  {
207  _regularizeCoefficients<printout>( min_var, min_sc, precision, max_sc, go_lp, PSDt, PSDn, Nc);
208 
209  if( min_sc == max_sc )
210  {
211  if( its == 0 )
212  {
213  min_sc -= precision;
214  max_sc = 200;
215  }
216  else
217  {
218  //std::cerr << "Error in regularizeCoefficients.\n";
219  //return -1;
220  break;
221  }
222  }
223  else
224  {
225  max_sc = min_sc + precision;
226  precision /= m_dPrecision;
227  }
228 
229  ++its;
230  }
231 
232  //Now record final values
233  if(calcCoefficients(PSDt, PSDn, PSDt[0]*pow(10, -min_sc/10), Nc) < 0) return -1;
234 
235  go_lp.a(lp._c);
236  //go_lp.a(std::vector<realT>({1}));
237  go_lp.b(lp._c);
238  //go_lp.b(std::vector<realT>({lp._c(0,0)}));
239 
240  realT ll = 0, ul = 0;
241  gmax_lp = go_lp.maxStableGain(ll,ul);
242  gopt_lp = go_lp.optGainOpenLoop(var_lp, PSDt, PSDn, gmax_lp);
243 
244  return 0;
245  }
246 
247  /// Regularize the PSD and calculate the associated LP coefficients.
248  /** The PSD is regularized by adding a constant to it. This constant is found by minimizing the variance of the residual PSD.
249  *
250  * \tparam printout if true then the results are printed to stdout as they are calculated.
251  */
252  template< bool printout=false>
253  int optimizeNc( realT & gmax_lp, ///< [out] the maximum gain calculated for the regularized PSD
254  realT & gopt_lp, ///< [out] the optimum gain calculated for the regularized PSD
255  int & Nc,
256  realT & var_lp, ///< [out] the variance at the optimum gain.
257  clGainOpt<realT> & go_lp, ///< [in] the gain optimization object
258  std::vector<realT> & PSDt, ///< [in] the turbulence PSD
259  std::vector<realT> & PSDn, ///< [in] the WFS noise PSD
260  int minNc, ///< [in] the number of coefficients
261  int maxNc
262  )
263  {
264  realT minVar = std::numeric_limits<realT>::max();
265 
266  for(int n = minNc; n <= maxNc; ++n)
267  {
268  realT _gmax_lp;
269  realT _gopt_lp;
270  realT _var_lp;
271  regularizeCoefficients<printout>(_gmax_lp, _gopt_lp, _var_lp, go_lp, PSDt, PSDn, n);
272 
273  if(_var_lp < minVar)
274  {
275  gmax_lp = _gmax_lp;
276  gopt_lp = _gopt_lp;
277  var_lp = _var_lp;
278  Nc = n;
279 
280  minVar = var_lp;
281  }
282  }
283 
284  return 0;
285  }
286 
287 };
288 
289 }//namespace analysis
290 }//namespace ao
291 }//namespace mx
292 
293 #endif // clAOLinearPredictor_hpp
Provides a class to manage closed loop gain optimization.
void augment1SidedPSD(vectorTout &psdTwoSided, vectorTin &psdOneSided, bool addZeroFreq=false, typename vectorTin::value_type scale=0.5)
Augment a 1-sided PSD to standard 2-sided FFT form.
Definition: psdUtils.hpp:794
The mxlib c++ namespace.
Definition: mxError.hpp:107
Class to manage the calculation of linear predictor coefficients for a closed-loop AO system.
realT m_gmax_lp
The maximum allowable gain for LP.
int calcCoefficients(std::vector< realT > &PSDt, std::vector< realT > &PSDn, realT PSDreg, int Nc, realT condition=0)
Calculate the LP coefficients for a turbulence PSD and a noise PSD.
int _regularizeCoefficients(realT &min_var, realT &min_sc, realT precision, realT max_sc, clGainOpt< realT > &go_lp, std::vector< realT > &PSDt, std::vector< realT > &PSDn, int Nc)
Worker function for regularizing the PSD for coefficient calculation.
int regularizeCoefficients(realT &gmax_lp, realT &gopt_lp, realT &var_lp, clGainOpt< realT > &go_lp, std::vector< realT > &PSDt, std::vector< realT > &PSDn, int Nc)
Regularize the PSD and calculate the associated LP coefficients.
int optimizeNc(realT &gmax_lp, realT &gopt_lp, int &Nc, realT &var_lp, clGainOpt< realT > &go_lp, std::vector< realT > &PSDt, std::vector< realT > &PSDn, int minNc, int maxNc)
Regularize the PSD and calculate the associated LP coefficients.
int calcCoefficients(std::vector< realT > &ac, size_t Nc, realT condition=0, size_t extrap=0)
Calculate the LP coefficients given an autocorrelation.