mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
aoSystem.hpp
Go to the documentation of this file.
1 /** \file aoSystem.hpp
2  * \author Jared R. Males (jaredmales@gmail.com)
3  * \brief Declares and defines an analytical AO system
4  * \ingroup mxAO_files
5  *
6  */
7 
8 //***********************************************************************//
9 // Copyright 2015-2022 Jared R. Males (jaredmales@gmail.com)
10 //
11 // This file is part of mxlib.
12 //
13 // mxlib is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // mxlib is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
25 //***********************************************************************//
26 
27 #ifndef aoSystem_hpp
28 #define aoSystem_hpp
29 
30 
31 #include "../../math/constants.hpp"
32 #include "../../math/roots.hpp"
33 #include "../../mxError.hpp"
34 #include "../../mxException.hpp"
35 
36 #include "aoConstants.hpp"
37 
38 
39 #include "aoAtmosphere.hpp"
40 #include "aoPSDs.hpp"
41 #include "aoWFS.hpp"
42 
43 
44 #define FITTING_ERROR_NO 0
45 #define FITTING_ERROR_ZERO 1
46 #define FITTING_ERROR_X 2
47 #define FITTING_ERROR_Y 3
48 
49 namespace mx
50 {
51 namespace AO
52 {
53 namespace analysis
54 {
55 
56 /// Describes an analytic adaptive optics (AO) system.
57 /**
58  * Templatized by the turbulence power spectral density (PSD).
59  *
60  * \tparam realT the floating point type used for all calculations
61  * \tparam inputSpecT specifies the turbulence spatial PSD type
62  * \tparam iosT is an output stream type with operator << defined (default is std::ostream)
63  *
64  * \ingroup mxAOAnalytic
65  */
66 template<typename _realT, class _inputSpectT, typename iosT = std::ostream>
67 class aoSystem
68 {
69 
70 public:
71 
72  typedef _realT realT;
73  typedef _inputSpectT inputSpectT;
75 
76  aoAtmosphereT atm;
77  inputSpectT psd;
78 
79 protected:
80 
81  realT m_D {0}; ///< Telescope diameter [m]
82 
83  std::vector<realT> m_d_min {0}; ///< Minimum AO system actuator pitch [m]. One per WFS mode.
84 
85  realT m_d_opt {0}; ///< Current optimum AO system actuator pitch [m]
86  bool m_optd {false}; ///< Flag controlling whether actuator pitch is optimized (true) or just uses m_d_min (false). Default: true.
87  realT m_optd_delta {1.0}; ///< The fractional change from d_min used in optimization. Set to 1 for integer binnings, > 1 for finer sampling.
88 
89  wfs<realT, iosT> * m_wfsBeta {nullptr}; ///< The WFS beta_p class.
90  bool m_ownWfsBeta {false}; ///< Flag indicating if the WFS beta_p pointer is owned by this instance.
91 
92  realT m_lam_wfs {0}; ///< WFS wavelength [m]
93 
94  //WFS detector parameters, which may be a function of binning
95  std::vector<realT> m_npix_wfs {0}; ///< Number of WFS pixels. One per WFS mode.
96  std::vector<realT> m_ron_wfs {0}; ///< WFS readout noise [electrons/pix]. One per WFS mode.
97  std::vector<realT> m_Fbg {0}; ///< Background flux, [photons/sec/pixel]. One per WFS mode.
98  std::vector<realT> m_minTauWFS {0}; ///< Minimum WFS exposure time [sec]. One per WFS mode.
99 
100  bool m_bin_npix {true}; ///< Flag controlling whether or not to bin WFS pixels according to the actuator spacing.
101 
102  int m_bin_opt {0}; ///< The optimum binning factor. If WFS modes are used, this is the mode index (0 to N-1). If not, it is 1 minus the pixel binning factor. It is always 1 minus the actuator binning factor.
103 
104  realT m_tauWFS {0}; ///< Actual WFS exposure time [sec]
105 
106  realT m_deltaTau {0}; ///< Loop latency [sec]
107 
108  bool m_optTau {true}; ///< Flag controlling whether optimum integration time is calculated (true) enforcing m_minTauWFS, or if m_tauWFS is used (false). Default: true.
109 
110  realT m_lam_sci {0}; ///< Science wavelength [m]
111 
112  realT m_zeta {0}; ///< Zenith angle [radians]
113  realT m_secZeta {1}; ///< Secant of the Zenith angle (calculated)
114 
115  int m_fit_mn_max {100}; ///< Maximum spatial frequency index to use for fitting error calculation.
116 
117  bool m_circularLimit {false}; ///< Flag to indicate that the spatial frequency limit is circular, not square.
118 
119  realT m_spatialFilter_ku {std::numeric_limits<realT>::max()}; ///< The spatial filter cutoff in u, [m^-1]
120  realT m_spatialFilter_kv {std::numeric_limits<realT>::max()}; ///< The spatial filter cutoff in v, [m^-1]
121 
122  realT m_ncp_wfe {0}; ///<Static WFE [m rms]
123  realT m_ncp_alpha {2}; ///< Power-law exponent for the NCP aberations. Default is 2.
124 
125  realT m_F0 {0}; ///< 0 mag flux from star at WFS [photons/sec]
126 
127  realT m_starMag {0}; ///< The magnitude of the star.
128 
129  bool m_specsChanged {true};///< Flag to indicate that a specification has changed.
130  bool m_dminChanged {true};///< Flag to indicate that d_min has changed.
131 
132  Eigen::Array<bool,-1,-1> m_controlledModes; ///< Map of which modes are under control. Set by calcStrehl.
133 
134  realT m_wfeMeasurement {0}; ///< Total WFE due to measurement a error [rad^2 at m_lam_sci]
135  realT m_wfeTimeDelay {0}; ///< Total WFE due to time delay [rad^2 at m_lam_sci]
136  realT m_wfeFitting {0}; ///< Total WFE due to fitting error [rad^2 at m_lam_sci]
137  realT m_wfeChromScintOPD {0}; ///< Total WFE due to the chromaticity of scintillation OPD [rad^2 at lam_sc]
138  realT m_wfeChromIndex {0}; ///< Total WFE due to the chromaticity of the index of refraction [rad^2 at lam_Sci]
139  realT m_wfeAnisoOPD {0}; ///< Total WFE due to dispersive anisoplanatism OPD.
140 
141  realT m_wfeNCP {0}; ///< Total WFE due to NCP errors [rad^2 at m_lam_sci]
142 
143  realT m_wfeVar {0}; ///< The WFE variance, in meters^2. Never use this directly, instead use wfeVar().
144  realT m_strehl {0}; ///< Strehl ratio, a calculated quantity. Never use this directdy, instead use strehl().
145 
146 
147 public:
148 
149  ///Default c'tor
150  /** Calls initialize().
151  */
152  aoSystem();
153 
154  ///Destructor
155  ~aoSystem();
156 
157  ///Load the default parameters from Guyon, 2005 \cite guyon_2005.
158  /**
159  *
160  */
161  void loadGuyon2005();
162 
163  ///Load parameters corresponding to the MagAO-X system.
164  void loadMagAOX();
165 
166  ///Load parameters corresponding to the G-MagAO-X system.
167  void loadGMagAOX();
168 
169  /// Set the value of the primary mirror diameter.
170  /**
171  */
172  void D( realT nD /**< [in] is the new value of m_D. */);
173 
174  /// Get the value of the primary mirror diamter
175  /**
176  * \returns the current value of m_D.
177  */
178  realT D();
179 
180  /// Set the minimum subaperture sampling for each WFS mode.
181  /** This sets the vector
182  */
183  void d_min( const std::vector<realT> & nd /**< [in] is the new values of m_d_min */);
184 
185  /// Set the minimum subaperture sampling for a given WFS mode
186  /** This sets the entry in the vector, if it has the proper length.
187  */
188  void d_min( int idx, ///< [in] the index of the WFS mode
189  realT nd ///< [in] is the new value of m_d_min[idx]
190  );
191 
192  /// Get the minimum subaperture sampling for a given WFS mode
193  /**
194  * \returns the current value of m_d_min[idx]
195  */
196  realT d_min( size_t idx /**< [in] the index of the WFS mode.*/);
197 
198  /// Get the minimum subaperture sampling for all WFS modes.
199  /**
200  * \returns the current value of m_d_min.
201  */
202  std::vector<realT> d_min();
203 
204  /// Set whether or not the value of d is optimized or just set to m_d_min.
205  /**
206  */
207  void optd( bool od /**< [in] is the new value of m_optd */);
208 
209  /// Get the value of m_optd.
210  /**
211  * \returns the new value of m_optd_delta.
212  */
213  bool optd();
214 
215  /// Set the fractional change in actuator spacing for optimization.
216  /** Sets the fraction of m_d_min by which the optimizer changes actautor spacing.
217  */
218  void optd_delta( realT odd /**< [in] is the new value of m_optd_delta */);
219 
220  /// Get the value of the fractional change in actuator spacing for optimization..
221  /**
222  * \returns the value of m_optd_delta.
223  */
224  realT optd_delta();
225 
226  /// Set the WFS Beta pointer
227  /** The WFS beta parameter determines the photon noise sensitivity.
228  *
229  * \tparam wfsT is a type derived from ao::analysis::wfs
230  */
231  template<typename wfsT>
232  void wfsBeta( const wfsT & w /**< [in] an object derived from ao::analysis::wfs base class*/);
233 
234  /// Set the WFS Beta pointer
235  /** The WFS beta parameter determines the photon noise sensitivity.
236  *
237  * \tparam wfsT is a type derived from ao::analysis::wfs
238  */
239  template<typename wfsT>
240  void wfsBeta( const wfsT * w /**< [in] pointer to an object derived from ao::analysis::wfs base class. If nullptr then a new object is allocated and managed.*/);
241 
242  /// Get the WFS Beta pointer
243  /**
244  * \returns a pointer to the current m_wfsBeta
245  */
247 
248  /// Get the value of beta_p for a spatial frequency
249  /** beta_p is the photon noise sensitivity of the WFS.
250  *
251  * \returns beta_p as calculated by the WFS.
252  */
253  realT beta_p( realT m, ///< [in] the spatial frequency index
254  realT n ///< [in] the spatial frequency index
255  );
256 
257  /// Get the value of beta_r for a spatial frequency
258  /** beta_r is the read noise sensitivity of the WFS.
259  *
260  * \returns beta_r as calculated by the WFS.
261  */
262  realT beta_r( realT m, ///< [in] the spatial frequency index
263  realT n ///< [in] the spatial frequency index
264  );
265 
266  /// Set the value of the WFS wavelength.
267  /**
268  */
269  void lam_wfs( realT nlam /**< [in] is the new value of m_lam_wfs */);
270 
271  /// Get the value of the WFS wavelength.
272  /**
273  * \returns the current value of m_lam_wfs.
274  */
275  realT lam_wfs();
276 
277  /// Set the number of pixels in the WFS for each WFS mode
278  /** This sets the vector.
279  */
280  void npix_wfs( const std::vector<realT> & npix /**< [in] is the new values of m_npix_wfs */);
281 
282  /// Set the number of pixels in the WFS for a given WFS mode
283  /** This sets the entry in the vector, if it has the proper length.
284  */
285  void npix_wfs( int idx, ///< [in] the index of the WFS mode
286  realT npix ///< [in] is the new value of m_npix_wfs[idx]
287  );
288 
289  /// Get the number of pixels in the WFS for a given WFS mode
290  /**
291  * \returns the current value of m_npix_wfs[idx]
292  */
293  realT npix_wfs(size_t idx /**< [in] the index of the WFS mode.*/);
294 
295  /// Get the number of pixels in the WFS for all WFS modes
296  /**
297  * \returns the current value of m_npix_wfs
298  */
299  std::vector<realT> npix_wfs();
300 
301  /// Set the value of the WFS readout noise for each WFS mode
302  /** This sets the vector.
303  */
304  void ron_wfs( const std::vector<realT> & nron /**< [in] is the new value of m_ron_wfs */);
305 
306  /// Set the value of the WFS readout noise for a given bining mode
307  /** This sets the entry in the vector if the vector has the proper length
308  */
309  void ron_wfs( int idx, ///< [in] the index of the WFS mode
310  realT nron ///< [in] is the new value of m_ron_wfs [idx]
311  );
312 
313  /// Get the value of the WFS readout noise for a given WFS mode
314  /**
315  * \returns the current value of m_ron_wfs[idx]
316  */
317  realT ron_wfs( size_t idx /**< [in] the index of the WFS mode.*/);
318 
319  /// Get the value of the WFS readout noise for all WFS modes
320  /**
321  * \returns the current value of m_ron_wfs
322  */
323  std::vector<realT> ron_wfs();
324 
325  /// Set the value of the background fluxes.
326  /** This sets the value of the background flux for each WFS mode
327  */
328  void Fbg(const std::vector<realT> & fbg /**< [in] is the new value of m_Fbg */);
329 
330  /// Set a single value of the background flux for a given WFS mode
331  /** This sets the entry in the vector if the vector has the proper length
332  */
333  void Fbg( int idx, ///< [in] the index of the WFS mode
334  realT fbg ///< [in] is the new value of m_Fbg[idx]
335  );
336 
337  /// Get the value of the background flux for a given WFS mode
338  /**
339  * \returns m_Fbg[idx]
340  */
341  realT Fbg( size_t idx /**< [in] the index of the WFS mode.*/);
342 
343  /// Get the value of the background flux for all WFS modes
344  /**
345  * \returns the current value of m_Fbg
346  */
347  std::vector<realT> Fbg();
348 
349  /// Set the value of the minimum WFS exposure times.
350  /** This sets the vector of the minimum WFS exposure times
351  */
352  void minTauWFS(const std::vector<realT> & ntau /**< [in] is the new value of m_minTauWFS */);
353 
354  /// Set a single value of the minimum WFS exposure time for a given WFS mode.
355  /** This sets the entry in the vector if the vector has sufficient length.
356  */
357  void minTauWFS(size_t idx, ///< [in] the index of the WFS mode
358  realT ntau ///< [in] is the new value of m_minTauWFS
359  );
360 
361  /// Get the value of the minimum WFS exposure time for a given binning.
362  /**
363  * \returns the current value of m_minTauWFS[idx].
364  */
365  realT minTauWFS(size_t idx /**< [in] the index of the WFS mode.*/);
366 
367  /// Get the values of the minimum WFS exposure time.
368  /**
369  * \returns the current value of m_minTauWFS.
370  */
371  std::vector<realT> minTauWFS();
372 
373  /// Set the value of the pixel binning flag
374  /**
375  */
376  void bin_npix(bool bnp /**< [in] is the new value of m_bin_npix */);
377 
378  /// Get the value of the pixel binngin flag
379  /**
380  * \returns
381  */
382  bool bin_npix();
383 
384  /// Get the value of the optimum binning factor/index.
385  /** If WFS modes are used, this is the mode index (0 to N-1). If not, it is 1 minus the pixel binning factor.
386  * It is always 1 minus the actuator binning factor.
387  * This calls opt_d() to perform the optimization if needed.
388  *
389  * \returns the current value of m_bin_opt.
390  */
391  int bin_opt();
392 
393  /// Set the value of the WFS exposure time.
394  /**
395  */
396  void tauWFS(realT ntau /**< [in] is the new value of m_tauWFS */);
397 
398  /// Get the value of the minimum WFS exposure time.
399  /**
400  * \returns the current value of m_tauWFS.
401  */
402  realT tauWFS();
403 
404  /// Set the value of m_deltaTau.
405  /**
406  */
407  void deltaTau(realT ndel /**< [in] is the new value of m_deltaTau*/);
408 
409  /// Get the value of m_deltaTau.
410  /**
411  * \returns the current value of m_deltaTau.
412  */
413  realT deltaTau();
414 
415  /// Set the value of m_optTau.
416  /**
417  */
418  void optTau( bool ot /**< [in] is the new value of m_optTau */);
419 
420  /// Get the value of m_optTau.
421  /**
422  * \returns the current value of m_optTau.
423  */
424  bool optTau();
425 
426  /// Set the science wavelength.
427  /**
428  */
429  void lam_sci(realT nlam /**< [in] is the new value of m_lam_sci */);
430 
431  /// Get the science wavelength.
432  /**
433  * \returns the current value of m_lam_sci.
434  */
435  realT lam_sci();
436 
437 
438  /// Set the zenith angle, and its secant.
439  /**
440  */
441  void zeta( realT nz /**< [in] The new value of m_zeta */ );
442 
443  /// Get the zenith angle
444  /**
445  * \return the current value of m_zeta
446  */
447  realT zeta();
448 
449  /// Get the zecant of the zenith angle
450  /**
451  * \return the current value of m_secZeta
452  */
453  realT secZeta();
454 
455  /// Set the value of m_fit_mn_max
456  /**
457  */
458  void fit_mn_max( int mnm /**< [in] is the new value of m_fit_mn_max */ );
459 
460  /// Get the value of m_fit_mn_max
461  /**
462  */
463  int fit_mn_max();
464 
465  /// Set the value of the circularLimit flag
466  /** If this is true, then the spatial frequency limits are treated as a circle
467  * rather than a square. This will create a circular dark hole.
468  */
469  void circularLimit( bool cl /**< [in] the new value of the circularLimit flag*/);
470 
471  /// Get the value of the circularLimit flag
472  /**
473  * \returns the current value of m_circularLimit
474  */
475  bool circularLimit();
476 
477  /// Set the value of spatialFilter_ku
478  /**
479  */
480  void spatialFilter_ku( realT ku /**< [in] is the new value of spatialFilter_ku*/ );
481 
482  /// Get the value of spatialFilter_ku
483  /** \returns the current value of m_spatialFilter_ku
484  */
485  realT spatialFilter_ku();
486 
487  /// Set the value of spatialFilter_kv
488  /**
489  */
490  void spatialFilter_kv( realT kv /**< [in] is the new value of spatialFilter_kv*/ );
491 
492  /// Get the value of spatialFilter_kv
493  /** \returns the current value of m_spatialFilter_kv
494  */
495  realT spatialFilter_kv();
496 
497  /// Set the value of the non-common path WFE.
498  /**
499  */
500  void ncp_wfe(realT nwfe /**< [in] is the new value of m_ncp_wfe*/);
501 
502  /// Get the value of the non-common path WFE.
503  /**
504  * \returns the current value of m_ncp_wfe.
505  */
506  realT ncp_wfe();
507 
508  /// Set the value of the non-common path WFE PSD index.
509  /**
510  */
511  void ncp_alpha(realT alpha /**< [in] is the new value of m_ncp_alpha*/);
512 
513  /// Get the value of the non-common path WFE PSD index.
514  /**
515  * \returns the current value of m_ncp_alpha.
516  */
517  realT ncp_alpha();
518 
519  /// Set the value of the 0 magnitude photon rate
520  /** This is the photon rate at the WFS, photons/sec.
521  *
522  */
523  void F0(realT nF0 /**< [in] is the new value of m_F0.*/);
524 
525  /// Get the value of the 0 magnitude photon rate
526  /**
527  * \returns the current value of m_F0.
528  */
529  realT F0();
530 
531  /// Set the value of the Star's magnitude
532  /**
533  */
534  void starMag(realT nmag /**< [in] is the new value of m_starMag.*/);
535 
536  /// Get the value of the Star's magnitude
537  /**
538  * \returns the current value of m_starMag
539  */
540  realT starMag();
541 
542  ///The photon flux at a given star magnitude.
543  /**
544  * \returns the photon flux of the star in the bandpass assumed by F0.
545  */
546  realT Fg( realT mag /**< [in] is the magnitude of the star. */);
547 
548  /// Get the photon rate at the current Star magnitude.
549  /** Calculates \f$ F_\gamma = F_0 10^{-0.4 m} \f$ where \f$ F_0 \f$ is m_F0 and \f$ m \f$ is m_starMag.
550  *
551  * \returns the current value of the current photon rate.
552  */
553  realT Fg();
554 
555  /// Access the array of controlledModes
556  /** This array indicates which modes are controlled after optimizeStrehl chooses them.
557  *
558  * \returns a const reference to m_controlledModes.
559  */
560  const Eigen::Array<bool, -1, -1> & controlledModes();
561 
562  /** \name Measurement Error
563  * Calculating the WFE due to WFS measurement noise.
564  * @{
565  */
566 
567  /// Calculate the terms of the signal to noise ratio squared (S/N)^2 for the WFS measurement
568  /** The S/N squared is
569  \f[
570  (S/N)^2 = \frac{ F_\gamma^2 \tau_{wfs}^2 }{ F_\gamma \tau_{wfs} + n_{pix} F_{bg} \tau_{wfs} + n_{pix} \sigma_{ron}^2 }
571  \f]
572 
573  *
574  * \returns the S/N squared
575  */
576  realT signal2Noise2( realT & Nph, ///< [out] the number of photons
577  realT tau_wfs, ///< [in] specifies the WFS exposure time. If 0, then optimumTauWFS is used
578  realT d, ///< [in] the actuator spacing in meters, used if binning WFS pixels
579  int b ///< [in] the binning parameter. Either the WFS mode index, or the binning factor minus 1.
580  );
581 
582  ///Calculate the measurement noise at a spatial frequency and specified actuator spacing
583  /** Calculates the wavefront phase variance due measurement noise at \f$ k = (m/D)\hat{u} + (n/D)\hat{v} \f$.
584  *
585  * \returns the measurement noise in rad^2 rms at the science wavelength
586  */
587  realT measurementError( realT m, ///< [in] specifies the u component of the spatial frequency
588  realT n, ///< [in] specifies the v component of the spatial frequency
589  realT d, ///< [in] the actuator spacing in meters
590  int b ///< [in] the binning parameter. Either the WFS mode index, or the binning factor minus 1.
591  );
592 
593  ///Calculate the total measurement error over all corrected spatial frequencies
594  /** This totals the measurement WFE at the optimum actuator spacing and binning.
595  *
596  * \overload
597  *
598  * \returns the total WFE due to measurement error.
599  */
600  realT measurementErrorTotal();
601 
602  ///@}
603 
604  /** \name Time Delay Error
605  * Calculating the WFE due to time delay.
606  * @{
607  */
608 
609  ///Calculate the time delay at a spatial frequency at the optimum exposure time and the specified actuator spacing
610  /** Calculates the wavefront phase variance due to time delay at \f$ f = (m/D)\hat{u} + (n/D)\hat{v} \f$.
611  *
612  * \returns the measurement noise in rad^2 rms at the science wavelength
613  */
614  realT timeDelayError( realT m, ///< [in] specifies the u component of the spatial frequency
615  realT n, ///< [in] specifies the v component of the spatial frequency
616  realT d, ///< [in] the actuator spacing, in meters
617  int b ///< [in] the binning parameter. Either the WFS mode index, or the binning factor minus 1.
618  );
619 
620  /// Calculate the time delay error over all corrected spatial frequencies
621  /** This totals the time delay WFE at the optimum actuator spacing and binning.
622  *
623  * \overload
624  *
625  * \returns the total WFE due to time delay.
626  */
627  realT timeDelayErrorTotal();
628 
629  ///@}
630 
631  /** \name Fitting Error
632  * Calculating the WFE due to uncorrected spatial frequencies.
633  * @{
634  */
635 
636  /// Calculate the fitting error at a specific spatial frequency.
637  /**
638  * \returns the fitting error in rad^2 rms at the science wavelength at (m,n).
639  */
640  realT fittingError( realT m, ///< [in] specifies the u component of the spatial frequency
641  realT n ///< [in] specifies the v component of the spatial frequency
642  );
643 
644  /// Calculate the total fitting error over all uncorrected spatial frequencies.
645  /** This totals the fitting WFE for the optimum actuator spacing and binning.
646  *
647  * \overload
648  *
649  * \returns the total fitting error.
650  */
651  realT fittingErrorTotal();
652 
653  ///@}
654 
655 
656  /** \name Chromatic Errors
657  * Calculating the WFE due to chromaticity in scintillaion, index of refraction, and dispersion.
658  * @{
659  */
660 
661  /// Calculate the wavefront error due to scintillation chromaticity in the OPD at a spatial frequency.
662  /** This totals the WFE from scintillation chromaticity in the OPD.
663  *
664  * \returns the WFE in rad^2 rms at the science wavelength at (m,n).
665  */
666  realT chromScintOPDError( int m, ///< [in] specifies the u component of the spatial frequency
667  int n ///< [in] specifies the v component of the spatial frequency
668  );
669 
670  /// Calculate the wavefront error due to scintillation chromaticity in the OPD over all spatial frequencies.
671  /** This totals the WFE from scintillation chromaticity in the OPD for the optimum actuator spacing.
672  *
673  * \overload
674  *
675  * \returns the WFE in rad^2 rms at the science wavelength at (m,n).
676  */
677  realT chromScintOPDErrorTotal();
678 
679  /// Calculate the wavefront error due to scintillation chromaticity in amplitude for a given spatial frequency.
680  /**
681  * \returns the WFE in rad^2 rms at the science wavelength at (m,n).
682  */
683  realT chromScintAmpError( int m, ///< [in] specifies the u component of the spatial frequency
684  int n ///< [in] specifies the v component of the spatial frequency
685  );
686 
687  /// Calculate the wavefront error due to scintillation chromaticity in amplitude over all spatial frequencies.
688  /**
689  * \returns the WFE in rad^2 rms at the science wavelength at (m,n).
690  */
692 
693  /// Calculate the wavefront error due to chromaticity in the index of refraction at a given spatial frequency.
694  /** This totals the WFE from chromaticity in the index of refraction.
695  *
696  * \overload
697  *
698  * \returns the WFE in rad^2 rms at the science wavelength at (m,n).
699  */
700  realT chromIndexError( int m, ///< [in] specifies the u component of the spatial frequency
701  int n ///< [in] specifies the v component of the spatial frequency
702  );
703 
704  /// Calculate the wavefront error due to chromaticity in the index of refraction at a specific spatial frequency.
705  /** This totals the WFE from chromaticity in the index of refraction for the optimum actuator spacing.
706  *
707  * \overload
708  *
709  * \returns the WFE in rad^2 rms at the science wavelength at (m,n).
710  */
711  realT chromIndexErrorTotal();
712 
713  /// Calculate the wavefront error due to dispersive anisoplanatism in the OPD at a given spatial frequency
714  /** This calculates the WFE from dispersive anisoplanatism in the OPD.
715  *
716  * \returns the WFE in rad^2 rms at the science wavelength at (m,n).
717  */
718  realT dispAnisoOPDError( int m, ///< [in] specifies the u component of the spatial frequency
719  int n ///< [in] specifies the v component of the spatial frequency
720  );
721 
722  /// Calculate the wavefront error due to dispersive anisoplanatism in the OPD over all specific spatial frequencies.
723  /** This totals the WFE from dispersive anisoplanatism in the OPD for the optimum actuator spacing.
724  *
725  * \overload
726  *
727  * \returns the WFE in rad^2 rms at the science wavelength at (m,n).
728  */
729  realT dispAnisoOPDErrorTotal();
730 
731  /// Calculate the wavefront error due to dispersive anisoplanatism in the amplitude at a specific spatial frequency.
732  /**
733  * \returns the WFE in rad^2 rms at the science wavelength at (m,n).
734  */
735  realT dispAnisoAmpError();
736 
737 
738  ///@}
739 
740  /** \name Optimum Parameters
741  * Functions to calculate the optimum integration time and actuator spacing.
742  *
743  * @{
744  */
745 
746  ///Calculate the optimum exposure time for a given spatial frequency at a specified actuator spacing
747  /** Finds the optimum exposure time at \f$ k = (m/D)\hat{u} + (n/D)\hat{v} \f$.
748  *
749  * \todo Check inclusion of X in parameters
750  *
751  * \returns the optimum expsoure time.
752  */
753  realT optimumTauWFS( realT m, ///< [in] is the spatial frequency index in u
754  realT n, ///< [in] is the spatial frequency index in v
755  realT d, ///< [in] the actuator spacing, in meters
756  int b ///< [in] the binning parameter. Either the WFS mode index, or the binning factor minus 1.
757  );
758 
759  ///Calculate the optimum exposure time for a given spatial frequency at the optimum actuator spacing.
760  /** Finds the optimum exposure time at \f$ k = (m/D)\hat{u} + (n/D)\hat{v} \f$.
761  * If optd == false this uses the minimum actuator spacing.
762  *
763  * \todo Check inclusion of X in parameters
764  *
765  * \returns the optimum expsoure time.
766  */
767  realT optimumTauWFS( realT m, ///< [in] is the spatial frequency index in u
768  realT n ///< [in] is the spatial frequency index in v
769  );
770 
771  ///Calculate the optimum actuator spacing.
772  /** Finds the value of m_d_opt where the fitting error is less than than the combined time delay and measurement error.
773  *
774  * \returns the current value of m_d_opt.
775  */
776  realT d_opt();
777 
778  /// @}
779 
780  /// Calculate the NCP variance at a spatial frequency.
781  /** Finds the NCP variance at \f$ k = (m/D)\hat{u} + (n/D)\hat{v} \f$.
782  *
783  * \returns the NCP variance at k.
784  */
785  realT ncpError( int m, ///< [in] is the spatial frequency index in u
786  int n ///< [in] is the spatial frequency index in v
787  );
788 
789  /// Calculate the total NCP variance in rad^2.
790  /**
791  * \returns the total NCP variance.
792  */
793  realT ncpError();
794 
795  /** \name Overall WFE and Strehl Ratio
796  * Functions to calculate the total WFE and Strehl ratio.
797  *
798  * @{
799  */
800 
801 protected:
802  ///Calculate the component WFE, total WFE, and Strehl ratio.
803  /** This should only be called when something changes.
804  */
805  void calcStrehl();
806 
807 public:
808  ///Get the current value of the total WFE variance.
809  /** If no changes, merely returns m_wfeVar. Calls calcStrehl if there are changes.
810  *
811  * \returns the current value of m_wfeVar;
812  */
813  realT wfeVar();
814 
815  ///Get the Strehl ratio for a given actuator pitch and WFS WFS mode.
816  /**
817  * Strehl is calculated using the extended Marechal approximation:
818  *
819  \f[
820  S = e^{-\sigma_{wfe}^2}
821  \f]
822  * where \f$ \sigma_{wfe}^2 \f$ is the WFE for the spacing and binning
823  *
824  * \returns the strehl for these values
825  */
826  realT strehl( realT d, ///< [in] the actuator spacing, in meters
827  int b ///< [in] the binning parameter. Either the WFS mode index, or the binning factor minus 1.
828  );
829 
830  ///Get the current Strehl ratio.
831  /** If no changes, merely returns m_strehl. Calls calcStrehl if there are changes.
832  * Strehl is calculated using the extended Marechal approximation:
833  *
834  \f[
835  S = e^{-\sigma_{wfe}^2}
836  \f]
837  * where \f$ \sigma_{wfe}^2 \f$ is the current value of m_wfeVar.
838  *
839  * \returns the current value of m_strehl.
840  */
841  realT strehl();
842 
843  /// @}
844 
845 
846  /** \name Contrast
847  * Calculating contrast
848  *
849  * @{
850  */
851 
852  /// Worker function for raw contrast fuctions
853  /** The logic in this calculation is the same regardless of component, except for the calculation of variance.
854  * The varFunc function pointer is used to calculate the variance, otherwise This handles the other details such
855  * as Strehl normalization, fitting error (if appropriate), and bounds checking.
856  *
857  * \note this gives the raw PSD, it must be convolved with the PSF for the true contrast.
858  *
859  * \tparam varFuncT is a function-pointer-to-member (of this class) with signature realT(*f)(realT, realT)
860  */
861  template<typename varFuncT>
862  realT C_( int m, ///< [in] is the spatial frequency index in u/
863  int n, ///< [in] is the spatial frequency index in v.
864  bool normStrehl, ///< [in] flag controls whether the contrast is normalized by Strehl ratio/
865  varFuncT varFunc, ///< [in] the variance function to use.
866  int doFittingError ///< [in] flag to describe how fitting error should be considered for this term: FITTING_ERROR_NO, FITTING_ERROR_ZERO, FITTING_ERROR_X, or FITTING_ERROR_Y.
867  );
868 
869  ///Worker function for the contrast-map functions.
870  /** The map calculation is the same for all terms, except for the calculation of variance at each pixel.
871  * The Cfunc function pointer is used to actually get the contrast.
872  *
873  * \note this is the raw PSD, it must be convolved with the PSF for the true contrast.
874  *
875  * \tparam imageT is an Eigen-like image
876  * \tparam CfuncT is a function-pointer-to-member (of this class) with signature realT (*f)(realT, realT, bool)
877  */
878  template<typename imageT, typename CfuncT>
879  void C_Map( imageT & im, ///< [out] the map image to be filled in.
880  CfuncT Cfunc, ///< [in] the raw contrast function to use for filling in the map.
881  bool normStrehl ///< [in] flag controlling whether or not the map is normalized by Strehl
882  );
883 
884  ///Calculate the residual variance due to uncorrected phase at a spatial frequency.
885  /** Used to calculate contrast \ref C0().
886  *
887  * \returns variance at (m,n).
888  */
889  realT C0var( realT m, ///< [in] is the spatial frequency index in u
890  realT n ///< [in] is the spatial frequency index in v
891  );
892 
893  ///Calculate the contrast due to uncorrected phase, C0.
894  /** Contrast C0 is the uncorrected phase, with the effects of scintillation included. See Guyon (2005) \cite guyon_2005, and the updated
895  * derivation in Males \& Guyon (2018) \cite males_guyon_2018.
896  *
897  * \note this is the raw PSD, it must be convolved with the PSF for the true contrast.
898  *
899  * \returns C0.
900  */
901  realT C0( realT m, ///< [in] is the spatial frequency index in u
902  realT n, ///< [in] is the spatial frequency index in v
903  bool normStrehl = true ///< [in] flag controls whether the contrast is normalized by Strehl ratio
904  );
905 
906  ///Calculate a 2D map of contrast C0
907  /**
908  * \tparam imageT is an Eigen-like image type.
909  */
910  template<typename imageT>
911  void C0Map( imageT & map, ///< [in] the map image to be filled in with contrast
912  bool normStrehl
913  );
914 
915  ///Calculate the residual variance due to uncorrected amplitude at a spatial frequency.
916  /** Used to calculate contrast \ref C1().
917  *
918  * \returns variance at (m,n).
919  */
920  realT C1var( realT m, ///< [in] is the spatial frequency index in u
921  realT n ///< [in] is the spatial frequency index in v
922  );
923 
924  ///Calculate the contrast due to uncorrected amplitude, C1.
925  /** Contrast C1 is the uncorrected amplitude due to scintillation. See Guyon (2005) \cite guyon_2005, and the updated
926  * derivation in Males \& Guyon (2018) \cite males_guyon_2018.
927  *
928  * \returns C0.
929  */
930  realT C1( realT m, ///< [in] is the spatial frequency index in u
931  realT n, ///< [in] is the spatial frequency index in v
932  bool normStrehl = true ///< [in] flag controls whether the contrast is normalized by Strehl ratio
933  );
934 
935  ///Calculate a 2D map of contrast C1.
936  /** The contrast is Strehl-normalized here.
937  *
938  * \note this is the raw PSD, it must be convolved with the PSF for the true contrast.
939  *
940  * \tparam imageT is an Eigen-like image type.
941  */
942  template<typename imageT>
943  void C1Map( imageT & map, ///< [in] the map image to be filled in with contrast
944  bool normStrehl
945  );
946 
947 
948  ///Calculate the residual variance due to measurement and time delay errors in phase/OPD at a spatial frequency.
949  /** Used to calculate contrast \ref C2().
950  *
951  * \returns variance at (m,n).
952  */
953  realT C2var( realT m, ///< [in] is the spatial frequency index in u
954  realT n ///< [in] is the spatial frequency index in v
955  );
956 
957  ///Calculate the contrast due to measurement and time delay errors in phase/OPD at a spatial frequency.
958  /** Contrast C2 is just the total variance due to time delay and measurement errors,
959  * divided by the Strehl ratio. See Guyon (2005) \cite guyon_2005, and the updated
960  * derivation in Males \& Guyon (2018) \cite males_guyon_2018.
961  *
962  * \returns C2.
963  */
964  realT C2( realT m, ///< [in] is the spatial frequency index in u
965  realT n, ///< [in] is the spatial frequency index in v
966  bool normStrehl = true ///< [in] flag controls whether the contrast is normalized by Strehl ratio.
967  );
968 
969  ///Calculate a 2D map of contrast \ref C2().
970  /** The contrast is Strehl-normalized here.
971  *
972  * \note this is the raw PSD, it must be convolved with the PSF for the true contrast.
973  *
974  * \tparam imageT is an Eigen-like image type.
975  */
976  template<typename imageT>
977  void C2Map( imageT & map, ///< [in] the map image to be filled in with contrast
978  bool normStrehl
979  );
980 
981  ///Calculate the residual variance due to measurement and time delay errors in amplitude at a spatial frequency.
982  /** Used to calculate contrast \ref C3().
983  *
984  * \returns variance at (m,n).
985  */
986  realT C3var( realT m, ///< [in] is the spatial frequency index in u
987  realT n ///< [in] is the spatial frequency index in v
988  );
989 
990  ///Calculate the contrast due to measurement and time delay errors in amplitude at a spatial frequency.
991  /** Contrast C3 is just the total variance due to time delay and measurement errors,
992  * divided by the Strehl ratio. See Guyon (2005) \cite guyon_2005, and the updated
993  * derivation in Males \& Guyon (2018) \cite males_guyon_2018.
994  *
995  * \returns C3.
996  */
997  realT C3( realT m, ///< [in] is the spatial frequency index in u
998  realT n, ///< [in] is the spatial frequency index in v
999  bool normStrehl = true ///< [in] flag controls whether the contrast is normalized by Strehl ratio.
1000  );
1001 
1002  ///Calculate a 2D map of contrast C3.
1003  /** The contrast is Strehl-normalized here.
1004  *
1005  * \note this is the raw PSD, it must be convolved with the PSF for the true contrast.
1006  *
1007  * \tparam imageT is an Eigen-like image type.
1008  */
1009  template<typename imageT>
1010  void C3Map( imageT & map, ///< [in] the map image to be filled in with contrast
1011  bool normStrehl
1012  );
1013 
1014 
1015  ///Calculate the residual variance due to scintilation-OPD chromaticity.
1016  /** Used to calculate contrast \ref C4().
1017  *
1018  * \returns variance at (m,n).
1019  */
1020  realT C4var( realT m, ///< [in] is the spatial frequency index in u
1021  realT n ///< [in] is the spatial frequency index in v
1022  );
1023 
1024  ///Calculate the contrast due to scintilation-OPD chromaticity.
1025  /** Contrast C4 is due to the chromaticity of scintillation, causing the ODP measurement to be slightly incorrect at the science wavelength.
1026  * See Guyon (2005) \cite guyon_2005, and the updated derivation in Males \& Guyon (2018) \cite males_guyon_2018.
1027  *
1028  * \returns C4.
1029  */
1030  realT C4( realT m, ///< [in] is the spatial frequency index in u
1031  realT n, ///< [in] is the spatial frequency index in v
1032  bool normStrehl = true ///< [in] flag controls whether the contrast is normalized by Strehl ratio.
1033  );
1034 
1035  ///Calculate a 2D map of contrast C4
1036  /** The contrast is Strehl-normalized here.
1037  *
1038  * \note this is the raw PSD, it must be convolved with the PSF for the true contrast.
1039  *
1040  * \tparam imageT is an Eigen-like image type.
1041  */
1042  template<typename imageT>
1043  void C4Map( imageT & map, ///< [in] the map image to be filled in with contrast
1044  bool normStrehl
1045  );
1046 
1047 
1048  ///Calculate the residual variance due to to scintilation-amplitude chromaticity.
1049  /** Used to calculate contrast \ref C5().
1050  *
1051  * \note this is the raw PSD, it must be convolved with the PSF for the true contrast.
1052  *
1053  * \returns variance at (m,n).
1054  */
1055  realT C5var( realT m, ///< [in] is the spatial frequency index in u
1056  realT n ///< [in] is the spatial frequency index in v
1057  );
1058 
1059  ///Calculate the contrast due to scintilation-amplitude chromaticity.
1060  /** Contrast C5 is due to the chromaticity of scintillation, causing the amplitude measurement to be slightly incorrect at
1061  * the science wavelength. See Guyon (2005) \cite guyon_2005, and the updated derivation in Males \& Guyon (2018) \cite males_guyon_2018.
1062  *
1063  * \returns C4.
1064  */
1065  realT C5( realT m, ///< [in] is the spatial frequency index in u
1066  realT n, ///< [in] is the spatial frequency index in v
1067  bool normStrehl = true ///< [in] flag controls whether the contrast is normalized by Strehl ratio.
1068  );
1069 
1070  ///Calculate a 2D map of contrast C5
1071  /** The contrast is Strehl-normalized here.
1072  *
1073  * \note this is the raw PSD, it must be convolved with the PSF for the true contrast.
1074  *
1075  * \tparam imageT is an Eigen-like image type.
1076  */
1077  template<typename imageT>
1078  void C5Map( imageT & map, ///< [in] the map image to be filled in with contrast
1079  bool normStrehl
1080  );
1081 
1082 
1083  ///Calculate the residual variance due to chromaticity of the index of refraction of air.
1084  /** Used to calculate contrast \ref C6().
1085  *
1086  * \returns variance at (m,n).
1087  */
1088  realT C6var( realT m, ///< [in] is the spatial frequency index in u
1089  realT n ///< [in] is the spatial frequency index in v
1090  );
1091 
1092  ///Calculate the contrast due to chromaticity of the index of refraction of air.
1093  /** Contrast C6 is due to the index of refraction of air being wavelength dependent, causing the ODP measurement to be slightly incorrect
1094  * at the science wavelength. See Guyon (2005) \cite guyon_2005, and the updated derivation in Males \& Guyon (2018) \cite males_guyon_2018.
1095  *
1096  * \returns C6.
1097  */
1098  realT C6( realT m, ///< [in] is the spatial frequency index in u
1099  realT n, ///< [in] is the spatial frequency index in v
1100  bool normStrehl = true ///< flag controls whether the contrast is normalized by Strehl ratio.
1101  );
1102 
1103  ///Calculate a 2D map of contrast C6
1104  /** The contrast is Strehl-normalized here.
1105  *
1106  * \note this is the raw PSD, it must be convolved with the PSF for the true contrast.
1107  *
1108  * \tparam imageT is an Eigen-like image type.
1109  */
1110  template<typename imageT>
1111  void C6Map( imageT & map, ///< [in] the map image to be filled in with contrast
1112  bool normStrehl
1113  );
1114 
1115 
1116  ///Calculate the residual variance due to dispersive anisoplanatism.
1117  /** Used to calculate contrast \ref C7().
1118  *
1119  * \returns variance at (m,n).
1120  */
1121  realT C7var( realT m, ///< [in] is the spatial frequency index in u
1122  realT n ///< [in] is the spatial frequency index in v
1123  );
1124 
1125  ///Calculate the contrast due to dispersive anisoplanatism.
1126  /** Contrast C7 is due to atmospheric dispersion causing light at different wavelengths to take different paths through atmospheric turbulence.
1127  * See Fitzgerald (2017, in prep) \cite fitzgerald_2017
1128  *
1129  * \returns C7.
1130  */
1131  realT C7( realT m, ///< [in] is the spatial frequency index in u
1132  realT n, ///< [in] is the spatial frequency index in v
1133  bool normStrehl = true ///< flag controls whether the contrast is normalized by Strehl ratio.
1134  );
1135 
1136  ///Calculate a 2D map of contrast C7
1137  /** The contrast is Strehl-normalized here.
1138  *
1139  * \note this is the raw PSD, it must be convolved with the PSF for the true contrast.
1140  *
1141  * \tparam imageT is an Eigen-like image type.
1142  */
1143  template<typename imageT>
1144  void C7Map( imageT & map, ///< [in] the map image to be filled in with contrast
1145  bool normStrehl
1146  );
1147 
1148 
1149  ///@}
1150 
1151  ///Output current parameters to a stream
1152  /** Outputs a formatted list of all current parameters.
1153  *
1154  */
1155  iosT & dumpAOSystem( iosT & ios /**< [in] a std::ostream-like stream. */);
1156 
1157 
1158  /// Setup the configurator to configure this class
1159  /**
1160  * todo: "\test Loading aoAtmosphere config settings \ref tests_ao_analysis_aoAtmosphere_config "[test doc]"
1161  */
1162  void setupConfig( app::appConfigurator & config /**< [in] the app::configurator object*/);
1163 
1164  /// Load the configuration of this class from a configurator
1165  /**
1166  * \todo: "\test Loading aoAtmosphere config settings \ref tests_ao_analysis_aoAtmosphere_config "[test doc]""
1167  */
1168  void loadConfig( app::appConfigurator & config /**< [in] the app::configurator object*/);
1169 };
1170 
1171 
1172 
1173 template<typename realT, class inputSpectT, typename iosT>
1175 {
1176  wfsBeta<wfs<realT,iosT>>(nullptr); //allocate a default ideal WFS.
1177 }
1178 
1179 template<typename realT, class inputSpectT, typename iosT>
1181 {
1182  if(m_wfsBeta && m_ownWfsBeta)
1183  {
1184  delete m_wfsBeta;
1185  }
1186 }
1187 
1188 template<typename realT, class inputSpectT, typename iosT>
1190 {
1191  atm.loadGuyon2005();
1192 
1193  F0(1.75e9*0.25*math::pi<realT>()*64.*0.18); //Converting to photons/sec
1194  lam_wfs(0.55e-6);
1195  lam_sci(1.6e-6);
1196  D(8.);
1197  starMag(5);
1198 
1199  //The rest of Guyon 05 is very ideal
1200  npix_wfs(std::vector<realT>({12868}));
1201  ron_wfs(std::vector<realT>({0.0}));
1202  Fbg(std::vector<realT>({0.0}));
1203 
1204  d_min( 8.0/1e3); //Allow super fine sampling
1205  minTauWFS( (realT) (1./1e9) ); // Just be super fast.
1206  tauWFS(1./1e9); //Just be super fast
1207 
1208  m_specsChanged = true;
1209  m_dminChanged = true;
1210 }
1211 
1212 template<typename realT, class inputSpectT, typename iosT>
1214 {
1215  atm.loadLCO();
1216  F0(4.2e10);
1217  lam_wfs(0.791e-6);
1218  lam_sci(0.656e-6);
1219 
1220  npix_wfs(std::vector<realT>({9024}));
1221  ron_wfs(std::vector<realT>({0.57}));
1222  Fbg(std::vector<realT>({0.22}));
1223 
1224  d_min(std::vector<realT>({6.5/48.0}));
1225  minTauWFS(std::vector<realT>({1./3622.}));
1226  tauWFS(1./3622.);
1227 
1228  D(6.5);
1229 
1230  m_specsChanged = true;
1231  m_dminChanged = true;
1232 }
1233 
1234 
1235 template<typename realT, class inputSpectT, typename iosT>
1237 {
1238 
1239  loadMagAOX();
1240 
1241 
1242  F0(7.6e10 * 368.0 / (0.25*math::pi<realT>()*6.5*6.5*(1.-0.29*0.29))); //Scaled up.
1243 
1244  D(25.4);
1245 
1246  m_specsChanged = true;
1247  m_dminChanged = true;
1248 }
1249 
1250 template<typename realT, class inputSpectT, typename iosT>
1252 {
1253  m_D = nD;
1254  psd.D(m_D);
1255 
1256  m_specsChanged = true;
1257  m_dminChanged = true;
1258 }
1259 
1260 template<typename realT, class inputSpectT, typename iosT>
1262 {
1263  return m_D;
1264 }
1265 
1266 template<typename realT, class inputSpectT, typename iosT>
1267 void aoSystem<realT, inputSpectT, iosT>::d_min(const std::vector<realT> & nd)
1268 {
1269  m_d_min.assign(nd.begin(), nd.end());
1270  m_specsChanged = true;
1271  m_dminChanged = true;
1272 }
1273 
1274 template<typename realT, class inputSpectT, typename iosT>
1276  realT nd
1277  )
1278 {
1279  if(m_d_min.size() < idx+1)
1280  {
1281  mxThrowException(err::sizeerr, "aoSystem::d_min", "idx larger than m_d_min");
1282  }
1283 
1284  m_d_min[idx] = nd;
1285 
1286  m_specsChanged = true;
1287  m_dminChanged = true;
1288 }
1289 
1290 template<typename realT, class inputSpectT, typename iosT>
1292 {
1293  if(m_d_min.size() < idx+1)
1294  {
1295  mxThrowException(err::sizeerr, "aoSystem::d_min", "idx larger than m_d_min");
1296  }
1297 
1298  return m_d_min[idx];
1299 }
1300 
1301 template<typename realT, class inputSpectT, typename iosT>
1303 {
1304  return m_d_min;
1305 }
1306 
1307 template<typename realT, class inputSpectT, typename iosT>
1309 {
1310  m_optd = od;
1311  m_specsChanged = true;
1312  m_dminChanged = true;
1313 }
1314 
1315 template<typename realT, class inputSpectT, typename iosT>
1317 {
1318  return m_optd;
1319 }
1320 
1321 template<typename realT, class inputSpectT, typename iosT>
1323 {
1324  m_optd_delta = odd;
1325  m_specsChanged = true;
1326  m_dminChanged = true;
1327 }
1328 
1329 template<typename realT, class inputSpectT, typename iosT>
1331 {
1332  return m_optd_delta;
1333 }
1334 
1335 template<typename realT, class inputSpectT, typename iosT>
1336 template<typename wfsT>
1338 {
1339  if(m_wfsBeta && m_ownWfsBeta)
1340  {
1341  delete m_wfsBeta;
1342  m_wfsBeta = nullptr;
1343  }
1344 
1345  m_wfsBeta = (wfs<realT,iosT> *) &w;
1346  m_ownWfsBeta = false;
1347 }
1348 
1349 template<typename realT, class inputSpectT, typename iosT>
1350 template<typename wfsT>
1352 {
1353  if(m_wfsBeta && m_ownWfsBeta)
1354  {
1355  delete m_wfsBeta;
1356  m_wfsBeta = nullptr;
1357  }
1358 
1359  if(w)
1360  {
1361  m_wfsBeta = (wfs<realT,iosT> *) w;
1362  m_ownWfsBeta = false;
1363  }
1364  else
1365  {
1366  m_wfsBeta = new wfsT;
1367  m_ownWfsBeta = true;
1368  }
1369 }
1370 
1371 template<typename realT, class inputSpectT, typename iosT>
1373 {
1374  return m_wfsBeta;
1375 }
1376 
1377 template<typename realT, class inputSpectT, typename iosT>
1379 {
1380  if( m_wfsBeta == 0) mxThrowException(err::paramnotset, "aoSystem::beta_p", "The WFS is not assigned.");
1381 
1382  return m_wfsBeta->beta_p(m, n, m_D, d_opt(), atm.r_0(m_lam_sci) );
1383 }
1384 
1385 template<typename realT, class inputSpectT, typename iosT>
1387 {
1388  if( m_wfsBeta == 0) mxThrowException(err::paramnotset, "aoSystem::beta_r", "The WFS is not assigned.");
1389 
1390  return m_wfsBeta->beta_r(m, n, m_D, d_opt(), atm.r_0(m_lam_sci) );
1391 }
1392 
1393 
1394 template<typename realT, class inputSpectT, typename iosT>
1396 {
1397  m_lam_wfs = nlam;
1398  m_specsChanged = true;
1399  m_dminChanged = true;
1400 }
1401 
1402 template<typename realT, class inputSpectT, typename iosT>
1404 {
1405  return m_lam_wfs;
1406 }
1407 
1408 template<typename realT, class inputSpectT, typename iosT>
1409 void aoSystem<realT, inputSpectT, iosT>::npix_wfs(const std::vector<realT> & npix)
1410 {
1411  m_npix_wfs.resize(npix.size());
1412  for(size_t n=0; n < npix.size(); ++n)
1413  {
1414  m_npix_wfs[n] = npix[n];
1415  }
1416 
1417  m_specsChanged = true;
1418  m_dminChanged = true;
1419 }
1420 
1421 template<typename realT, class inputSpectT, typename iosT>
1423  realT npix
1424  )
1425 {
1426  if(m_npix_wfs.size() < idx+1)
1427  {
1428  mxThrowException(err::sizeerr, "aoSystem::npix_wfs", "idx larger than m_npix_wfs");
1429  }
1430 
1431  m_npix_wfs[idx] = npix;
1432 
1433  m_specsChanged = true;
1434  m_dminChanged = true;
1435 }
1436 
1437 template<typename realT, class inputSpectT, typename iosT>
1439 {
1440  if(m_npix_wfs.size() < idx+1)
1441  {
1442  mxThrowException(err::sizeerr, "aoSystem::npix_wfs", "idx larger than m_npix_wfs");
1443  }
1444 
1445  return m_npix_wfs[idx];
1446 }
1447 
1448 template<typename realT, class inputSpectT, typename iosT>
1450 {
1451  return m_npix_wfs;
1452 }
1453 
1454 template<typename realT, class inputSpectT, typename iosT>
1455 void aoSystem<realT, inputSpectT, iosT>::ron_wfs(const std::vector<realT> & nron)
1456 {
1457  m_ron_wfs.resize(nron.size());
1458  for(size_t n=0; n < nron.size(); ++n)
1459  {
1460  m_ron_wfs[n] = nron[n];
1461  }
1462 
1463  m_specsChanged = true;
1464  m_dminChanged = true;
1465 }
1466 
1467 template<typename realT, class inputSpectT, typename iosT>
1469  realT nron
1470  )
1471 {
1472  if(m_ron_wfs.size() < idx+1)
1473  {
1474  mxThrowException(err::sizeerr, "aoSystem::ron_wfs", "idx larger than m_ron_wfs");
1475  }
1476 
1477  m_ron_wfs[idx] = nron;
1478 
1479  m_specsChanged = true;
1480  m_dminChanged = true;
1481 }
1482 
1483 
1484 template<typename realT, class inputSpectT, typename iosT>
1486 {
1487  if(m_ron_wfs.size() < idx+1)
1488  {
1489  mxThrowException(err::sizeerr, "aoSystem::ron_wfs", "idx larger than m_ron_wfs");
1490  }
1491 
1492  return m_ron_wfs[idx];
1493 }
1494 
1495 template<typename realT, class inputSpectT, typename iosT>
1497 {
1498  return m_ron_wfs;
1499 }
1500 
1501 template<typename realT, class inputSpectT, typename iosT>
1502 void aoSystem<realT, inputSpectT, iosT>::Fbg(const std::vector<realT> & fbg)
1503 {
1504  m_Fbg.resize(fbg.size());
1505  for(size_t n=0; n < fbg.size(); ++n)
1506  {
1507  m_Fbg[n] = fbg[n];
1508  }
1509 
1510  m_specsChanged = true;
1511  m_dminChanged = true;
1512 }
1513 
1514 template<typename realT, class inputSpectT, typename iosT>
1516  realT fbg
1517  )
1518 {
1519  if(m_Fbg.size() < idx+1)
1520  {
1521  mxThrowException(err::sizeerr, "aoSyste,::Fbg", "idx larger than m_Fbg");
1522  }
1523 
1524  m_Fbg[idx] = fbg;
1525 
1526  m_specsChanged = true;
1527  m_dminChanged = true;
1528 }
1529 
1530 template<typename realT, class inputSpectT, typename iosT>
1532 {
1533  if(m_Fbg.size() < idx+1)
1534  {
1535  mxThrowException(err::sizeerr, "aoSyste,::Fbg", "idx larger than m_Fbg");
1536  }
1537 
1538  return m_Fbg[idx];
1539 }
1540 
1541 template<typename realT, class inputSpectT, typename iosT>
1543 {
1544  return m_Fbg;
1545 }
1546 
1547 template<typename realT, class inputSpectT, typename iosT>
1548 void aoSystem<realT, inputSpectT, iosT>::minTauWFS(const std::vector<realT> & ntau)
1549 {
1550  m_minTauWFS.resize(ntau.size());
1551  for(size_t n=0; n < ntau.size(); ++n)
1552  {
1553  m_minTauWFS[n] = ntau[n];
1554  }
1555 
1556  m_specsChanged = true;
1557  m_dminChanged = true;
1558 }
1559 
1560 template<typename realT, class inputSpectT, typename iosT>
1562  realT ntau
1563  )
1564 {
1565  if(m_minTauWFS.size() < idx+1)
1566  {
1567  mxThrowException(err::sizeerr, "aoSystem::minTauWFS", "idx larger than m_ntau_wfs");
1568  }
1569 
1570  m_minTauWFS[idx] = ntau;
1571 
1572  m_specsChanged = true;
1573  m_dminChanged = true;
1574 }
1575 
1576 template<typename realT, class inputSpectT, typename iosT>
1578 {
1579  if(m_minTauWFS.size() < idx+1)
1580  {
1581  mxThrowException(err::sizeerr, "aoSystem::minTauWFS", "idx larger than m_ntau_wfs");
1582  }
1583 
1584  return m_minTauWFS[idx];
1585 }
1586 
1587 template<typename realT, class inputSpectT, typename iosT>
1589 {
1590  return m_minTauWFS;
1591 }
1592 
1593 template<typename realT, class inputSpectT, typename iosT>
1595 {
1596  if(bnp != m_bin_npix)
1597  {
1598  m_bin_npix = bnp;
1599  m_specsChanged = true;
1600  m_dminChanged = true;
1601  }
1602 }
1603 
1604 template<typename realT, class inputSpectT, typename iosT>
1606 {
1607  return m_bin_npix;
1608 }
1609 
1610 template<typename realT, class inputSpectT, typename iosT>
1612 {
1613  d_opt();
1614  return m_bin_opt;
1615 }
1616 
1617 
1618 template<typename realT, class inputSpectT, typename iosT>
1620 {
1621  m_tauWFS = ntau;
1622  m_specsChanged = true;
1623  m_dminChanged = true;
1624 }
1625 
1626 template<typename realT, class inputSpectT, typename iosT>
1628 {
1629  return m_tauWFS;
1630 }
1631 
1632 template<typename realT, class inputSpectT, typename iosT>
1634 {
1635  m_deltaTau = ndel;
1636  m_specsChanged = true;
1637  m_dminChanged = true;
1638 }
1639 
1640 template<typename realT, class inputSpectT, typename iosT>
1642 {
1643  return m_deltaTau;
1644 }
1645 
1646 template<typename realT, class inputSpectT, typename iosT>
1648 {
1649  m_optTau = ot;
1650  m_specsChanged = true;
1651  m_dminChanged = true;
1652 }
1653 
1654 template<typename realT, class inputSpectT, typename iosT>
1656 {
1657  return m_optTau;
1658 }
1659 
1660 template<typename realT, class inputSpectT, typename iosT>
1662 {
1663  m_lam_sci = nlam;
1664  m_specsChanged = true;
1665  m_dminChanged = true;
1666 }
1667 
1668 template<typename realT, class inputSpectT, typename iosT>
1670 {
1671  return m_lam_sci;
1672 }
1673 
1674 template<typename realT, class inputSpectT, typename iosT>
1676 {
1677  m_zeta = nz;
1678  m_secZeta = 1/cos(m_zeta);
1679 
1680  m_specsChanged = true;
1681  m_dminChanged = true;
1682 }
1683 
1684 template<typename realT, class inputSpectT, typename iosT>
1686 {
1687  return m_zeta;
1688 }
1689 
1690 template<typename realT, class inputSpectT, typename iosT>
1692 {
1693  return m_secZeta;
1694 }
1695 
1696 template<typename realT, class inputSpectT, typename iosT>
1698 {
1699  if(mnm < 0) mnm = 0;
1700  m_fit_mn_max = mnm;
1701 }
1702 
1703 template<typename realT, class inputSpectT, typename iosT>
1705 {
1706  return m_fit_mn_max;
1707 }
1708 
1709 template<typename realT, class inputSpectT, typename iosT>
1711 {
1712  m_circularLimit = cl;
1713  m_specsChanged = true;
1714  m_dminChanged = true;
1715 }
1716 
1717 template<typename realT, class inputSpectT, typename iosT>
1719 {
1720  return m_circularLimit;
1721 }
1722 
1723 template<typename realT, class inputSpectT, typename iosT>
1725 {
1726  m_spatialFilter_ku = fabs(kx);
1727  m_specsChanged = true; //not sure if needed
1728  m_dminChanged = true; //not sure if needed
1729 }
1730 
1731 template<typename realT, class inputSpectT, typename iosT>
1733 {
1734  return m_spatialFilter_ku;
1735 }
1736 
1737 template<typename realT, class inputSpectT, typename iosT>
1739 {
1740  m_spatialFilter_kv = fabs(ky);
1741  m_specsChanged = true; //not sure if needed
1742  m_dminChanged = true; //not sure if needed
1743 }
1744 
1745 template<typename realT, class inputSpectT, typename iosT>
1747 {
1748  return m_spatialFilter_kv;
1749 }
1750 
1751 template<typename realT, class inputSpectT, typename iosT>
1753 {
1754  m_ncp_wfe = nwfe;
1755  m_specsChanged = true;
1756  m_dminChanged = true;
1757 }
1758 
1759 template<typename realT, class inputSpectT, typename iosT>
1761 {
1762  return m_ncp_wfe;
1763 }
1764 
1765 template<typename realT, class inputSpectT, typename iosT>
1767 {
1768  m_ncp_alpha = alpha;
1769  m_specsChanged = true;
1770  m_dminChanged = true;
1771 }
1772 
1773 template<typename realT, class inputSpectT, typename iosT>
1775 {
1776  return m_ncp_alpha;
1777 }
1778 
1779 template<typename realT, class inputSpectT, typename iosT>
1781 {
1782  m_F0 = nF0;
1783  m_specsChanged = true;
1784  m_dminChanged = true;
1785 }
1786 
1787 template<typename realT, class inputSpectT, typename iosT>
1789 {
1790  return m_F0;
1791 }
1792 
1793 template<typename realT, class inputSpectT, typename iosT>
1795 {
1796  m_starMag = nmag;
1797  m_specsChanged = true;
1798  m_dminChanged = true;
1799 }
1800 
1801 template<typename realT, class inputSpectT, typename iosT>
1803 {
1804  return m_starMag;
1805 }
1806 
1807 template<typename realT, class inputSpectT, typename iosT>
1809 {
1810  return m_F0*pow(10.0, -0.4*mag);
1811 }
1812 
1813 template<typename realT, class inputSpectT, typename iosT>
1815 {
1816  return Fg(m_starMag);
1817 }
1818 
1819 template<typename realT, class inputSpectT, typename iosT>
1820 const Eigen::Array<bool, -1, -1> & aoSystem<realT, inputSpectT, iosT>::controlledModes()
1821 {
1822  return m_controlledModes;
1823 }
1824 
1825 template<typename realT, class inputSpectT, typename iosT>
1827  realT tau_wfs,
1828  realT d,
1829  int b
1830  )
1831 {
1832  Nph = Fg()*tau_wfs;
1833 
1834  double binfact = 1.0;
1835  int binidx = 0;
1836  if( m_bin_npix )
1837  {
1838  if(m_npix_wfs.size() == 1) //Only if "true binning", otherwise the WFS mode vectors handle it.
1839  {
1840  binfact = 1./pow((realT) b+1,2);
1841  }
1842  else binidx = b;
1843  }
1844 
1845  return pow(Nph,2)/( m_npix_wfs[binidx]*binfact * ( m_Fbg[binidx]*tau_wfs + pow(m_ron_wfs[binidx],2)));
1846 }
1847 
1848 template<typename realT, class inputSpectT, typename iosT>
1850  realT n,
1851  realT d,
1852  int b
1853  )
1854 {
1855  if(m ==0 and n == 0) return 0;
1856 
1857  realT tau_wfs;
1858 
1859  if(m_optTau) tau_wfs = optimumTauWFS(m, n, d, b);
1860  else tau_wfs = m_tauWFS;
1861 
1862  if (m_wfsBeta == 0) mxThrowException(err::paramnotset, "aoSystem::measurementError", "The WFS is not assigned.");
1863 
1864  realT beta_p = m_wfsBeta->beta_p(m,n,m_D, d, atm.r_0(m_lam_wfs));
1865  realT beta_r = m_wfsBeta->beta_r(m,n,m_D, d, atm.r_0(m_lam_wfs));
1866  realT Nph = 0;
1867  realT snr2 = signal2Noise2( Nph, tau_wfs, d, b );
1868 
1869  return (pow(beta_r,2)/snr2 + pow(beta_p,2)/Nph) *pow(m_lam_wfs/m_lam_sci, 2);
1870 }
1871 
1872 template<typename realT, class inputSpectT, typename iosT>
1874 {
1875  if(m_specsChanged || m_dminChanged ) calcStrehl();
1876  return m_wfeMeasurement;
1877 }
1878 
1879 template<typename realT, class inputSpectT, typename iosT>
1881  realT n,
1882  realT d,
1883  int b
1884  )
1885 {
1886  if(m ==0 and n == 0) return 0;
1887 
1888  realT k = sqrt(m*m + n*n)/m_D;
1889 
1890  realT tau_wfs;
1891 
1892  if(m_optTau) tau_wfs = optimumTauWFS(m, n, d, b);
1893  else tau_wfs = m_tauWFS;
1894 
1895  realT tau = tau_wfs + m_deltaTau;
1896 
1897  ///\todo handle multiple layers
1898  return psd(atm, 0, k, m_secZeta)/pow(m_D,2) * pow(atm.lam_0()/m_lam_sci, 2) * sqrt(atm.X(k, m_lam_sci, m_secZeta)) * pow(math::two_pi<realT>()*atm.v_wind()*k,2) * pow(tau,2);
1899 }
1900 
1901 template<typename realT, class inputSpectT, typename iosT>
1903 {
1904  if(m_specsChanged || m_dminChanged ) calcStrehl();
1905  return m_wfeTimeDelay;
1906 }
1907 
1908 
1909 template<typename realT, class inputSpectT, typename iosT>
1911  realT n )
1912 {
1913  realT k = sqrt(m*m+n*n)/m_D;
1914 
1915  ///\todo handle multiple layers
1916  return psd(atm, 0, k, m_secZeta)/pow(m_D,2) * pow(atm.lam_0()/m_lam_sci, 2);
1917 }
1918 
1919 template<typename realT, class inputSpectT, typename iosT>
1921 {
1922  if(m_specsChanged || m_dminChanged ) calcStrehl();
1923  return m_wfeFitting;
1924 }
1925 
1926 template<typename realT, class inputSpectT, typename iosT>
1928  int n
1929  )
1930 {
1931  return C4var(m,n);
1932 }
1933 
1934 template<typename realT, class inputSpectT, typename iosT>
1936 {
1937  if(m_specsChanged || m_dminChanged ) calcStrehl();
1938  return m_wfeChromScintOPD;
1939 }
1940 
1941 template<typename realT, class inputSpectT, typename iosT>
1943  int n
1944  )
1945 {
1946  return C5var(m,n);
1947 
1948 #if 0
1949  int mn_max = floor(0.5*m_D/d_opt());
1950 
1951  realT sum = 0;
1952 
1953  for(int m = -mn_max; m <= mn_max; ++m)
1954  {
1955  for(int n = -mn_max; n <= mn_max; ++n)
1956  {
1957  if(n == 0 && m == 0) continue;
1958 
1959  sum += C5var(m,n);
1960  }
1961  }
1962 
1963  return sum;
1964 #endif
1965 }
1966 
1967 template<typename realT, class inputSpectT, typename iosT>
1969  int n
1970  )
1971 {
1972  return C6var(m,n);
1973 }
1974 
1975 template<typename realT, class inputSpectT, typename iosT>
1977 {
1978  if(m_specsChanged || m_dminChanged ) calcStrehl();
1979  return m_wfeChromIndex;
1980 }
1981 
1982 template<typename realT, class inputSpectT, typename iosT>
1984  int n
1985  )
1986 {
1987  return C7var(m,n);
1988 }
1989 
1990 template<typename realT, class inputSpectT, typename iosT>
1992 {
1993  if(m_specsChanged || m_dminChanged ) calcStrehl();
1994  return m_wfeAnisoOPD;
1995 }
1996 
1997 template<typename realT, class inputSpectT, typename iosT>
1999 {
2000  return 0;
2001 
2002 #if 0
2003  int mn_max = floor(0.5*m_D/d_opt());
2004 
2005  realT sum = 0;
2006 
2007  for(int m = -mn_max; m <= mn_max; ++m)
2008  {
2009  for(int n = -mn_max; n <= mn_max; ++n)
2010  {
2011  if(n == 0 && m == 0) continue;
2012 
2013  if( m_circularLimit )
2014  {
2015  if( m*m + n*n > mn_max*mn_max ) continue;
2016  }
2017 
2018  sum += C8var(m,n);
2019  }
2020  }
2021 
2022  return sum;
2023 #endif
2024 }
2025 
2026 template<typename realT, class inputSpectT, typename iosT>
2028  realT n,
2029  realT dact, //here called dact due to parameter collision with root-finding
2030  int bbin
2031  )
2032 {
2033  if(m_D == 0)
2034  {
2035  mxError("aoSystem::optimumTauWFS", MXE_PARAMNOTSET, "Diameter (D) not set.");
2036  return -1;
2037  }
2038 
2039  if(m_F0 == 0)
2040  {
2041  mxError("aoSystem::optimumTauWFS", MXE_PARAMNOTSET, "0-mag photon flux (F0) not set.");
2042  return -1;
2043  }
2044 
2045  double binfact = 1.0;
2046  int binidx = 0; //index into WFS configurations
2047  if( m_bin_npix )
2048  {
2049  if(m_npix_wfs.size() > 1)
2050  {
2051  binidx = bbin;
2052  }
2053  else
2054  {
2055  binfact = 1.0/pow((realT) (bbin+1),2);
2056  }
2057  }
2058 
2059  realT k = sqrt(m*m + n*n)/m_D;
2060 
2061  realT F = Fg();
2062 
2063  if (m_wfsBeta == 0) mxThrowException(err::paramnotset, "aoSystem::beta_p", "The WFS is not assigned.");
2064 
2065  realT beta_p = m_wfsBeta->beta_p(m,n,m_D, dact, atm.r_0(m_lam_wfs));
2066  realT beta_r = m_wfsBeta->beta_r(m,n,m_D, dact, atm.r_0(m_lam_wfs));
2067 
2068  //Set up for root finding:
2069  realT a, b, c, d, e;
2070 
2071  ///\todo handle multiple layers
2072  realT Atmp = 2*pow(atm.lam_0(),2)*psd(atm, 0, k, m_secZeta)/pow(m_D,2)*(atm.X(k, m_lam_wfs, m_secZeta))*pow(math::two_pi<realT>()*atm.v_wind()*k,2);
2073 
2074  a = Atmp;
2075  b = Atmp *m_deltaTau;
2076  c = 0;
2077  d = -1*(pow(m_lam_wfs,2) / F) * ( (m_npix_wfs[binidx]*binfact*m_Fbg[binidx] / F)*pow(beta_r,2) + pow(beta_p,2));
2078  e = -2*pow(m_lam_wfs,2) * (m_npix_wfs[binidx]*binfact)*pow(m_ron_wfs[binidx],2) * pow(beta_r,2) / pow(F,2);
2079 
2080  std::vector<std::complex<realT> > x;
2081 
2082  //Get the roots
2083  math::quarticRoots(x, a, b , c, d, e);
2084 
2085  //Now pick the largest positive real root
2086  realT tauopt = 0.0;
2087 
2088  for(int i=0; i<4; i++)
2089  {
2090  if( real(x[i]) > 0 && imag(x[i]) == 0 && real(x[i]) > tauopt) tauopt = real(x[i]);
2091  }
2092 
2093  if(tauopt < m_minTauWFS[binidx]) tauopt = m_minTauWFS[binidx];
2094 
2095  return tauopt;
2096 
2097 
2098 }
2099 
2100 template<typename realT, class inputSpectT, typename iosT>
2102  realT n )
2103 {
2104  d_opt(); //also gets m_bin_opt;
2105  return optimumTauWFS(m, n, m_d_opt, m_bin_opt);
2106 }
2107 
2108 
2109 template<typename realT, class inputSpectT, typename iosT>
2111 {
2112  if(!m_dminChanged) return m_d_opt;
2113 
2114  //Validate the modes
2115  ///\todo this should be in a separate valideModes function
2116  if(m_npix_wfs.size() < 1)
2117  {
2118  mxThrowException(err::sizeerr, "aoSystem::d_opt", "npix_wfs must have at least one entry");
2119  }
2120 
2121  if(m_d_min.size() != m_npix_wfs.size())
2122  {
2123  mxThrowException(err::sizeerr, "aoSystem::d_opt", "d_min must be the same size as npix_wfs");
2124  }
2125 
2126  if(m_ron_wfs.size() != m_npix_wfs.size())
2127  {
2128  mxThrowException(err::sizeerr, "aoSystem::d_opt", "ron_wfs must be the same size as npix_wfs");
2129  }
2130 
2131  if(m_Fbg.size() != m_npix_wfs.size())
2132  {
2133  mxThrowException(err::sizeerr, "aoSystem::d_opt", "F_bg must be the same size as npix_wfs");
2134  }
2135 
2136  if(m_minTauWFS.size() != m_npix_wfs.size())
2137  {
2138  mxThrowException(err::sizeerr, "aoSystem::d_opt", "minTauWFS must be the same size as npix_wfs");
2139  }
2140 
2141  ///\todo investigate why we tolerate m_d_min = 0 here. Is this just a config error?
2142  if( m_d_min.size() == 1 && m_d_min[0] == 0 )
2143  {
2144  m_d_opt = 1e-50;
2145  m_bin_opt = 0;
2146  m_dminChanged = false;
2147  return m_d_opt;
2148  }
2149 
2150  if(!m_optd)
2151  {
2152  m_d_opt = m_d_min[0];
2153  m_bin_opt = 0;
2154  m_dminChanged = false;
2155 
2156  return m_d_opt;
2157  }
2158 
2159 
2160  realT best_d = 0;
2161 
2162  if(m_bin_npix)
2163  {
2164  if(m_npix_wfs.size() > 1) //Optimize over the WFS modes
2165  {
2166  int best_idx = 0;
2167  best_d = m_d_min[0];
2168 
2169  realT bestStrehlOverall = 0;
2170 
2171  for(int b=0; b < m_npix_wfs.size(); ++b)
2172  {
2173  realT d = m_d_min[b];
2174  realT s = strehl(d,b);
2175  realT bestStrehl = s;
2176 
2177  //Find the actuator pitch at which AO error is less than fitting error at Nyquist
2178  while( d < m_D/2 )
2179  {
2180  d += m_d_min[b]/m_optd_delta;
2181  s = strehl(d,b);
2182 
2183  if(s < bestStrehl) //Strehl got worse. Can't be <= otherwise small m_optd_deltas will immediately out
2184  {
2185  d -= m_d_min[b]/m_optd_delta; //go back to previous d
2186  break;
2187  }
2188  else bestStrehl = s;
2189  }
2190 
2191  //Check if this is optimum so far
2192  if(bestStrehl >= bestStrehlOverall) // >= to favor fewer actuators
2193  {
2194  bestStrehlOverall = bestStrehl;
2195  best_idx = b;
2196  best_d = d;
2197 
2198  }
2199  }
2200 
2201  m_bin_opt = best_idx;
2202  }
2203  else
2204  {
2205  realT d = m_d_min[0];
2206  m_bin_opt = 0;
2207 
2208  realT s = strehl(d,m_bin_opt);
2209  realT bestStrehl = s;
2210 
2211  while( d < m_D/2 )
2212  {
2213  d += m_d_min[0]/m_optd_delta;
2214  m_bin_opt = d/m_d_min[0] - 1;
2215  if(m_bin_opt < 0) m_bin_opt = 0;
2216 
2217  s = strehl(d,m_bin_opt);
2218 
2219  if(s < bestStrehl) //Strehl got worse. Can't be <= otherwise small m_optd_deltas will immediately out
2220  {
2221  d -= m_d_min[0]/m_optd_delta; //go back to previous d
2222  m_bin_opt = d/m_d_min[0] - 1;
2223  if(m_bin_opt < 0) m_bin_opt = 0;
2224  break;
2225  }
2226  else bestStrehl = s;
2227  }
2228  best_d = d;
2229  }
2230  }
2231  else
2232  {
2233  realT d = m_d_min[0];
2234  m_bin_opt = 0;
2235 
2236  realT s = strehl(d,m_bin_opt);
2237  realT bestStrehl = s;
2238 
2239  //Find the actuator pitch which minimizes total error (AO error is less than fitting error at Nyquist)
2240  while( d < m_D/2 )
2241  {
2242  d += m_d_min[0]/m_optd_delta;
2243 
2244  s = strehl(d,m_bin_opt);
2245  if(s < bestStrehl) //Strehl got worse. Can't be <= otherwise small m_optd_deltas will immediately out
2246  {
2247  d -= m_d_min[0]/m_optd_delta; //go back to previous d
2248  break;
2249  }
2250  else bestStrehl = s;
2251  }
2252  best_d = d;
2253  }
2254 
2255  m_d_opt = best_d;
2256  m_dminChanged = false;
2257 
2258  return m_d_opt;
2259 }
2260 
2261 
2262 template<typename realT, class inputSpectT, typename iosT>
2264  int n )
2265 {
2266  if(m ==0 and n == 0) return 0;
2267 
2268  realT k = sqrt(m*m + n*n)/m_D;
2269 
2270  return (m_ncp_alpha - 2)/(math::two_pi<realT>()) * pow(m_D, -m_ncp_alpha) * ncpError() * pow(k, -m_ncp_alpha);
2271 }
2272 
2273 template<typename realT, class inputSpectT, typename iosT>
2275 {
2276  return pow(m_ncp_wfe,2)*pow(math::two_pi<realT>()/m_lam_sci,2);
2277 }
2278 
2279 template<typename realT, class inputSpectT, typename iosT>
2281  int b
2282  )
2283 {
2284 
2285  int mn_max = floor(0.5*m_D/d);
2286 
2287  realT wfeVar = 0;
2288 
2289  bool controlled;
2290  for(int m = -m_fit_mn_max; m <= m_fit_mn_max; ++m)
2291  {
2292  for(int n = -m_fit_mn_max; n <= m_fit_mn_max; ++n)
2293  {
2294  controlled = false;
2295  if(m_circularLimit)
2296  {
2297  if( m*m + n*n <= mn_max*mn_max) controlled = true;
2298  }
2299  else
2300  {
2301  if( abs(m) <= mn_max && abs(n) <= mn_max) controlled = true;
2302  }
2303 
2304  if(controlled)
2305  {
2306  realT wfeMeasurement = measurementError(m,n, d, b);
2307  realT wfeTimeDelay = timeDelayError(m,n,d, b);
2308  realT wfeChromScintOPD = chromScintOPDError(m,n);
2309  realT wfeChromIndex = chromIndexError(m,n);
2310  realT wfeAnisoOPD = dispAnisoOPDError(m,n);
2311 
2312  realT wfeFitting = fittingError(m,n);
2313 
2314  if(wfeFitting < wfeMeasurement + wfeTimeDelay + wfeChromScintOPD + wfeChromIndex + wfeAnisoOPD)
2315  {
2316  wfeVar += wfeFitting;
2317  }
2318  else
2319  {
2320  wfeVar += wfeMeasurement + wfeTimeDelay + wfeChromScintOPD + wfeChromIndex + wfeAnisoOPD;
2321  }
2322  }
2323  else
2324  {
2325  wfeVar += fittingError(m,n);
2326  }
2327 
2328  realT wfeNCP = ncpError(m, n);
2329  wfeVar += wfeNCP;
2330  }
2331  }
2332 
2333  return exp(-1 * wfeVar);
2334 
2335 }
2336 
2337 template<typename realT, class inputSpectT, typename iosT>
2339 {
2340  realT d = d_opt(); //have to run this to get m_bin_opt set.
2341  int b = m_bin_opt;
2342 
2343  int mn_max = floor(0.5*m_D/d);
2344 
2345  m_wfeMeasurement = 0;
2346  m_wfeTimeDelay = 0;
2347  m_wfeChromScintOPD = 0;
2348  m_wfeChromIndex = 0;
2349  m_wfeAnisoOPD = 0;
2350 
2351  m_wfeFitting = 0;
2352 
2353  m_wfeNCP = 0;
2354 
2355 
2356  m_controlledModes.resize(2*m_fit_mn_max+1, 2*m_fit_mn_max+1);
2357  m_controlledModes.setZero();
2358 
2359  bool controlled;
2360  for(int m = -m_fit_mn_max; m <= m_fit_mn_max; ++m)
2361  {
2362  for(int n = -m_fit_mn_max; n <= m_fit_mn_max; ++n)
2363  {
2364  controlled = false;
2365  if(m_circularLimit)
2366  {
2367  if( m*m + n*n <= mn_max*mn_max) controlled = true;
2368  }
2369  else
2370  {
2371  if( abs(m) <= mn_max && abs(n) <= mn_max) controlled = true;
2372  }
2373 
2374  if(controlled)
2375  {
2376  realT wfeMeasurement = measurementError(m,n, d, b);
2377  realT wfeTimeDelay = timeDelayError(m,n,d, b);
2378  realT wfeChromScintOPD = chromScintOPDError(m,n);
2379  realT wfeChromIndex = chromIndexError(m,n);
2380  realT wfeAnisoOPD = dispAnisoOPDError(m,n);
2381 
2382  realT wfeFitting = fittingError(m,n);
2383 
2384  if(wfeFitting < wfeMeasurement + wfeTimeDelay + wfeChromScintOPD + wfeChromIndex + wfeAnisoOPD)
2385  {
2386  m_wfeFitting += wfeFitting;
2387  }
2388  else //it's worth controlling this mode.
2389  {
2390  m_wfeMeasurement += wfeMeasurement;
2391  m_wfeTimeDelay += wfeTimeDelay;
2392  m_wfeChromScintOPD += wfeChromScintOPD;
2393  m_wfeChromIndex += wfeChromIndex;
2394  m_wfeAnisoOPD += wfeAnisoOPD;
2395  m_controlledModes(m_fit_mn_max+m, m_fit_mn_max+n) = 1;
2396  }
2397  }
2398  else
2399  {
2400  m_wfeFitting += fittingError(m,n);
2401  }
2402 
2403  m_wfeNCP += ncpError(m, n);
2404  }
2405  }
2406 
2407  m_wfeVar = m_wfeMeasurement + m_wfeTimeDelay + m_wfeFitting + m_wfeChromScintOPD +m_wfeChromIndex + m_wfeAnisoOPD + m_wfeNCP;
2408 
2409  m_strehl = exp(-1 * m_wfeVar);
2410 
2411  m_specsChanged = false;
2412 }
2413 
2414 template<typename realT, class inputSpectT, typename iosT>
2416 {
2417  if(m_specsChanged || m_dminChanged ) calcStrehl();
2418 
2419  return m_wfeVar;
2420 }
2421 
2422 template<typename realT, class inputSpectT, typename iosT>
2424 {
2425  if( m_specsChanged || m_dminChanged ) calcStrehl();
2426 
2427  return m_strehl;
2428 }
2429 
2430 template<typename realT, class inputSpectT, typename iosT>
2431 template<typename varFuncT>
2433  int n,
2434  bool normStrehl,
2435  varFuncT varFunc,
2436  int doFittingError
2437  )
2438 {
2439  if(m ==0 && n == 0) return 0;
2440 
2441  //we run this to optimize regardless of whether we use it
2442  // if already optimized then this is a minor hit
2443  realT S = strehl();
2444 
2445  if(!normStrehl) S = 1;
2446 
2447  if( doFittingError != FITTING_ERROR_NO)
2448  {
2449  int mn_max = m_D/(2.*d_opt());
2450 
2451  if( m_controlledModes(m_fit_mn_max+m, m_fit_mn_max+n) == false)
2452  {
2453  if(doFittingError == FITTING_ERROR_ZERO) return 0;
2454 
2455  realT fe = fittingError(m,n);
2456 
2457  realT k = sqrt(m*m + n*n)/m_D;
2458 
2459  if(doFittingError == FITTING_ERROR_X) fe *= (atm.X(k, m_lam_sci, m_secZeta));
2460  else if(doFittingError == FITTING_ERROR_Y) fe *= (atm.Y(k, m_lam_sci, m_secZeta));
2461  else
2462  {
2463  std::cerr << "Unknown doFittingError\n";
2464  exit(-1);
2465  }
2466 
2467  return fe / S;
2468  }
2469  }
2470  //get if not doing fitting error or if inside control region:
2471 
2472  realT var = (this->*varFunc)(m, n);
2473 
2474  return var/S;
2475 }
2476 
2477 template<typename realT, class inputSpectT, typename iosT>
2478 template<typename imageT, typename CfuncT>
2480  CfuncT Cfunc,
2481  bool normStrehl
2482  )
2483 {
2484  int dim1=im.rows();
2485  int dim2=im.cols();
2486 
2487  int mc = 0.5*(dim1-1);
2488  int nc = 0.5*(dim2-1);
2489 
2490  for(int i=0; i< dim1; ++i)
2491  {
2492  int m = i - mc;
2493 
2494  for(int j=0; j< dim2; ++j)
2495  {
2496  int n = j - nc;
2497 
2498  im(i,j) = (this->*Cfunc)(m, n, normStrehl);
2499  }
2500  }
2501 }
2502 
2503 template<typename realT, class inputSpectT, typename iosT>
2505  realT n
2506  )
2507 {
2508  realT k = sqrt(m*m + n*n)/m_D;
2509  ///\todo handle multiple layers
2510  return psd(atm, 0, k, m_secZeta)/pow(m_D,2) * pow(atm.lam_0()/m_lam_sci, 2) * (atm.X(k, m_lam_sci, m_secZeta));
2511 }
2512 
2513 template<typename realT, class inputSpectT, typename iosT>
2515  realT n,
2516  bool normStrehl
2517  )
2518 {
2519 
2520  return C_(m,n,normStrehl,&aoSystem<realT, inputSpectT, iosT>::C0var, FITTING_ERROR_NO);
2521 }
2522 
2523 template<typename realT, class inputSpectT, typename iosT>
2524 template<typename imageT>
2526  bool normStrehl
2527  )
2528 {
2529  C_Map(im, &aoSystem<realT, inputSpectT, iosT>::C0, normStrehl);
2530 }
2531 
2532 template<typename realT, class inputSpectT, typename iosT>
2534  realT n
2535  )
2536 {
2537  realT k = sqrt(m*m + n*n)/m_D;
2538 
2539  ///\todo handle multiple layers
2540  return psd(atm, 0, k, m_secZeta)/pow(m_D,2) * pow(atm.lam_0()/m_lam_sci, 2) * (atm.Y(k, m_lam_sci, m_secZeta));
2541 }
2542 
2543 template<typename realT, class inputSpectT, typename iosT>
2545  realT n,
2546  bool normStrehl
2547  )
2548 {
2549  return C_(m,n,normStrehl,&aoSystem<realT, inputSpectT, iosT>::C1var, FITTING_ERROR_NO);
2550 }
2551 
2552 template<typename realT, class inputSpectT, typename iosT>
2553 template<typename imageT>
2555  bool normStrehl
2556  )
2557 {
2558  C_Map(im, &aoSystem<realT, inputSpectT, iosT>::C1, normStrehl);
2559 }
2560 
2561 template<typename realT, class inputSpectT, typename iosT>
2563  realT n
2564  )
2565 {
2566  d_opt();
2567  return measurementError(m, n, d_opt(), m_bin_opt) + timeDelayError(m,n, d_opt(), m_bin_opt);
2568 }
2569 
2570 template<typename realT, class inputSpectT, typename iosT>
2572  realT n,
2573  bool normStrehl
2574  )
2575 {
2576  return C_(m,n,normStrehl,&aoSystem<realT, inputSpectT, iosT>::C2var, FITTING_ERROR_X);
2577 }
2578 
2579 template<typename realT, class inputSpectT, typename iosT>
2580 template<typename imageT>
2582  bool normStrehl
2583  )
2584 {
2585  C_Map(im, &aoSystem<realT, inputSpectT, iosT>::C2, normStrehl);
2586 }
2587 
2588 template<typename realT, class inputSpectT, typename iosT>
2590  realT n
2591  )
2592 {
2593  return 0;//measurementError(m, n) + timeDelayError(m,n);
2594 }
2595 
2596 template<typename realT, class inputSpectT, typename iosT>
2598  realT n,
2599  bool normStrehl
2600  )
2601 {
2602  return C_(m,n,normStrehl,&aoSystem<realT, inputSpectT, iosT>::C3var, FITTING_ERROR_ZERO);//FITTING_ERROR_Y);
2603 }
2604 
2605 template<typename realT, class inputSpectT, typename iosT>
2606 template<typename imageT>
2608  bool normStrehl
2609  )
2610 {
2611  C_Map(im, &aoSystem<realT, inputSpectT, iosT>::C3, normStrehl);
2612 }
2613 
2614 template<typename realT, class inputSpectT, typename iosT>
2616  realT n
2617  )
2618 {
2619  realT k = sqrt(m*m + n*n)/m_D;
2620 
2621  ///\todo handle multiple layers
2622  //This does not need to be divided by X b/c we haven't multiplied by it, this is is C0/X.
2623  return psd(atm, 0, k, m_secZeta)/pow(m_D,2) * pow(atm.lam_0()/m_lam_sci, 2) * atm.dX(k, m_lam_sci, m_lam_wfs);
2624 }
2625 
2626 
2627 template<typename realT, class inputSpectT, typename iosT>
2629  realT n,
2630  bool normStrehl
2631  )
2632 {
2633  return C_(m,n,normStrehl,&aoSystem<realT, inputSpectT, iosT>::C4var, FITTING_ERROR_ZERO);
2634 }
2635 
2636 template<typename realT, class inputSpectT, typename iosT>
2637 template<typename imageT>
2639  bool normStrehl
2640  )
2641 {
2642  C_Map(im, &aoSystem<realT, inputSpectT, iosT>::C4, normStrehl);
2643 }
2644 
2645 template<typename realT, class inputSpectT, typename iosT>
2647  realT n
2648  )
2649 {
2650  realT k = sqrt(m*m + n*n)/m_D;
2651 
2652  ///\todo handle multiple layers
2653  //This does not need to be divided by Y b/c we haven't multiplied by it, this is is C1/Y.
2654  return psd(atm, 0, k, m_secZeta)/pow(m_D,2) * pow(atm.lam_0()/m_lam_sci, 2) * atm.dY(k, m_lam_sci, m_lam_wfs);
2655 }
2656 
2657 
2658 template<typename realT, class inputSpectT, typename iosT>
2660  realT n,
2661  bool normStrehl
2662  )
2663 {
2664  return C_(m,n,normStrehl,&aoSystem<realT, inputSpectT, iosT>::C5var, FITTING_ERROR_ZERO);
2665 }
2666 
2667 template<typename realT, class inputSpectT, typename iosT>
2668 template<typename imageT>
2670  bool normStrehl
2671  )
2672 {
2673  C_Map(im, &aoSystem<realT, inputSpectT, iosT>::C5, normStrehl);
2674 }
2675 
2676 template<typename realT, class inputSpectT, typename iosT>
2678  realT n
2679  )
2680 {
2681  realT ni = atm.n_air(m_lam_sci);
2682  realT nw = atm.n_air(m_lam_wfs);
2683 
2684  return C0var(m, n) * pow( (ni-nw)/(ni-1), 2); //Fixes error in Eqn 29
2685 }
2686 
2687 
2688 template<typename realT, class inputSpectT, typename iosT>
2690  realT n,
2691  bool normStrehl
2692  )
2693 {
2694  return C_(m,n,normStrehl,&aoSystem<realT, inputSpectT, iosT>::C6var, FITTING_ERROR_ZERO);
2695 }
2696 
2697 template<typename realT, class inputSpectT, typename iosT>
2698 template<typename imageT>
2700  bool normStrehl
2701  )
2702 {
2703  C_Map(im, &aoSystem<realT, inputSpectT, iosT>::C6, normStrehl);
2704 }
2705 
2706 template<typename realT, class inputSpectT, typename iosT>
2708  realT n
2709  )
2710 {
2711  realT k = sqrt(m*m + n*n)/m_D;
2712 
2713  ///\todo this needs to handle multiple layers -- do we violate an assumption of L_0 isn't constant?
2714  return psd(atm, 0, k, m_secZeta)/pow(m_D,2) * pow(atm.lam_0()/m_lam_sci, 2) * atm.X_Z(k, m_lam_wfs, m_lam_sci, m_secZeta);
2715 }
2716 
2717 template<typename realT, class inputSpectT, typename iosT>
2719  realT n,
2720  bool normStrehl
2721  )
2722 {
2723  return C_(m,n,normStrehl,&aoSystem<realT, inputSpectT, iosT>::C7var, FITTING_ERROR_ZERO);
2724 }
2725 
2726 template<typename realT, class inputSpectT, typename iosT>
2727 template<typename imageT>
2729  bool normStrehl
2730  )
2731 {
2732  C_Map(im, &aoSystem<realT, inputSpectT, iosT>::C7, normStrehl);
2733 }
2734 
2735 template<typename realT, class inputSpectT, typename iosT>
2737 {
2738  ios << "# AO Params:\n";
2739  ios << "# D = " << D() << '\n';
2740 
2741  if(m_d_min.size() > 0)
2742  {
2743  ios << "# d_min = " << d_min((size_t) 0);
2744  for(size_t n=1; n < m_d_min.size(); ++n) ios << ',' << d_min(n);
2745  ios << '\n';
2746  }
2747  else ios << "# d_min = null\n";
2748 
2749  ios << "# optd = " << std::boolalpha << m_optd << '\n';
2750  ios << "# d_opt_delta = " << optd_delta() << '\n';
2751  ios << "# lam_sci = " << lam_sci() << '\n';
2752  ios << "# F0 = " << F0() << '\n';
2753  ios << "# starMag = " << starMag() << '\n';
2754  ios << "# lam_sci = " << lam_sci() << '\n';
2755  ios << "# zeta = " << zeta() << '\n';
2756  ios << "# lam_wfs = " << lam_wfs() << '\n';
2757 
2758  if(npix_wfs().size() > 0)
2759  {
2760  ios << "# npix_wfs = " << npix_wfs((size_t) 0);
2761  for(size_t n=1; n < npix_wfs().size(); ++n) ios << ',' << npix_wfs(n);
2762  ios << '\n';
2763  }
2764  else ios << "# npix_wfs = null\n";
2765 
2766  if(ron_wfs().size() > 0)
2767  {
2768  ios << "# ron_wfs = " << ron_wfs((size_t) 0);
2769  for(size_t n=1; n < ron_wfs().size(); ++n) ios << ',' << ron_wfs(n);
2770  ios << '\n';
2771  }
2772  else ios << "# ron_wfs = null\n";
2773 
2774  if(Fbg().size() > 0)
2775  {
2776  ios << "# Fbg = " << Fbg((size_t) 0);
2777  for(size_t n=1; n < Fbg().size(); ++n) ios << ',' << Fbg(n);
2778  ios << '\n';
2779  }
2780  else ios << "# Fbg = null\n";
2781 
2782  if(minTauWFS().size() > 0)
2783  {
2784  ios << "# minTauWFS = " << minTauWFS((size_t) 0);
2785  for(size_t n=1; n < minTauWFS().size(); ++n) ios << ',' << minTauWFS(n);
2786  ios << '\n';
2787  }
2788  else ios << "# minTauWFS = null\n";
2789 
2790  ios << "# bin_npix = " << std::boolalpha << m_bin_npix << '\n';
2791  ios << "# tauWFS = " << tauWFS() << '\n';
2792  ios << "# optTau = " << std::boolalpha << m_optTau << '\n';
2793  ios << "# deltaTau = " << deltaTau() << '\n';
2794  ios << "# fit_mn_max = " << m_fit_mn_max << '\n';
2795  ios << "# spatialFilter_ku = " << m_spatialFilter_ku << '\n';
2796  ios << "# spatialFilter_kv = " << m_spatialFilter_kv << '\n';
2797  ios << "# ncp_wfe = " << m_ncp_wfe << '\n';
2798  ios << "# ncp_alpha = " << m_ncp_alpha << '\n';
2799 
2800 
2801  if (m_wfsBeta == 0) mxThrowException(err::paramnotset, "aoSystem::beta_p", "The WFS is not assigned.");
2802  m_wfsBeta->dumpWFS(ios);
2803  psd.dumpPSD(ios);
2804  atm.dumpAtmosphere(ios);
2805 
2806  dumpGitStatus(ios);
2807 
2808  return ios;
2809 }
2810 
2811 template<typename realT, class inputSpectT, typename iosT>
2813 {
2814  using namespace mx::app;
2815 
2816  //AO System configuration
2817  config.add("aosys.wfs" ,"", "aosys.wfs" , argType::Required, "aosys", "wfs", false, "string", "The WFS type: idealWFS, unmodPyWFS, asympModPyWFS, shwfs, calculatedWFS");
2818  config.add("aosys.wfs_beta_p" ,"", "aosys.wfs_beta_p" , argType::Required, "aosys", "wfs_beta_p", false, "string", "The beta_p file path for calcualtedWFS");
2819  config.add("aosys.wfs_beta_r" ,"", "aosys.wfs_beta_r" , argType::Required, "aosys", "wfs_beta_r", false, "string", "The beta_r file path for calcualtedWFS");
2820  config.add("aosys.wfs_sensitivity" ,"", "aosys.wfs_sensitivity" , argType::Required, "aosys", "wfs_sensitivity", false, "bool", "Flag indicating that beta_p/beta_r are sensitivities (inverse) [default false]");
2821  config.add("aosys.D" ,"", "aosys.D" , argType::Required, "aosys", "D", false, "real", "The telescope diameter [m]");
2822  config.add("aosys.d_min" ,"", "aosys.d_min" , argType::Required, "aosys", "d_min", false, "real", "The minimum actuator spacing [m]");
2823  config.add("aosys.optd" ,"", "aosys.optd" , argType::Optional, "aosys", "optd", false, "bool", "Whether or not the actuator spacing is optimized");
2824  config.add("aosys.optd_delta" ,"", "aosys.optd_delta" , argType::Required, "aosys", "optd_delta", false, "bool", "The fractional change from d_min used in optimization. Set to 1 (default) for integer binnings, > 1 for finer sampling.");
2825  config.add("aosys.F0" ,"", "aosys.F0" , argType::Required, "aosys", "F0", false, "real", "Zero-mag photon flux, [photons/sec]");
2826  config.add("aosys.lam_wfs" ,"", "aosys.lam_wfs" , argType::Required, "aosys", "lam_wfs", false, "real", "WFS wavelength [m]" );
2827  config.add("aosys.npix_wfs" ,"", "aosys.npix_wfs" , argType::Required, "aosys", "npix_wfs", false, "vector<real>", "The number of pixels in the WFS");
2828  config.add("aosys.ron_wfs" ,"", "aosys.ron_wfs" , argType::Required, "aosys", "ron_wfs", false, "vector<real>", "WFS readout noise [photons/read]");
2829  config.add("aosys.bin_npix" ,"", "aosys.bin_npix" , argType::Required, "aosys", "bin_npix", false, "bool", "Whether or not WFS pixels are re-binned along with actuator spacing optimization");
2830  config.add("aosys.Fbg" ,"", "aosys.Fbg" , argType::Required, "aosys", "Fbg", false, "vector<real>", "Background counts, [counts/pix/sec]");\
2831  config.add("aosys.tauWFS" ,"", "aosys.tauWFS" , argType::Required, "aosys", "tauWFS", false, "real", "WFS integration time [s]");
2832  config.add("aosys.minTauWFS" ,"", "aosys.minTauWFS" , argType::Required, "aosys", "minTauWFS", false, "vector<real>", "Minimum WFS integration time [s]");
2833  config.add("aosys.deltaTau" ,"", "aosys.deltaTau" , argType::Required, "aosys", "deltaTau", false, "real", "Loop delay [s]");
2834  config.add("aosys.optTau" ,"", "aosys.optTau" , argType::Optional, "aosys", "optTau", false, "bool", "Whether or not the integration time is optimized");
2835  config.add("aosys.lam_sci" ,"", "aosys.lam_sci" , argType::Required, "aosys", "lam_sci", false, "real", "Science wavelength [m]");
2836  config.add("aosys.zeta" ,"", "aosys.zeta" , argType::Required, "aosys", "zeta", false, "real", "Zenith distance [rad]");
2837  config.add("aosys.fit_mn_max" ,"", "aosys.fit_mn_max" , argType::Required, "aosys", "fit_mn_max", false, "real", "Maximum spatial frequency index to use for analysis");
2838  config.add("aosys.circularLimit" ,"", "aosys.circularLimit" , argType::Optional, "aosys", "circularLimit", false, "bool", " Flag to indicate that the spatial frequency limit is circular, not square.");
2839  config.add("aosys.spatialFilter_ku", "", "aosys.spatialFilter_ku", argType::Required, "aosys", "spatialFilter_ku", false, "real", "Spatial filter cutoff frequency in u [m^-1]");
2840  config.add("aosys.spatialFilter_kv", "", "aosys.spatialFilter_kv", argType::Required, "aosys", "spatialFilter_kv", false, "real", "Spatial filter cutoff frequency in v [m^-1]");
2841  config.add("aosys.ncp_wfe" ,"", "aosys.ncp_wfe" , argType::Required, "aosys", "ncp_wfe", false, "real", "NCP WFE between 1 lambda/D and fit_mn_max [rad^2]");
2842  config.add("aosys.ncp_alpha" ,"", "aosys.ncp_alpha" , argType::Required, "aosys", "ncp_alpha", false, "real", "PSD index for NCP WFE");
2843  config.add("aosys.starMag" ,"", "aosys.starMag" , argType::Required, "aosys", "starMag", false, "real", "Star magnitude");
2844  config.add("aosys.starMags" ,"", "aosys.starMags" , argType::Required, "aosys", "starMags", false, "real vector", "A vector of star magnitudes");
2845 
2846  atm.setupConfig(config);
2847  psd.setupConfig(config);
2848 
2849 }
2850 
2851 template<typename realT, class inputSpectT, typename iosT>
2853 {
2854  //WFS
2855  if(config.isSet("aosys.wfs"))
2856  {
2857  std::string wfsStr;
2858  config(wfsStr, "aosys.wfs");
2859 
2860  if(wfsStr == "ideal")
2861  {
2862  wfsBeta<wfs<realT,iosT>>(nullptr);
2863  }
2864  else if(wfsStr == "unmodPyWFS")
2865  {
2866  wfsBeta<pywfsUnmod<realT,iosT>>(nullptr);
2867  }
2868  else if(wfsStr == "asympModPyWFS")
2869  {
2870  wfsBeta<pywfsModAsymptotic<realT>>(nullptr);
2871  }
2872  else if(wfsStr == "SHWFS")
2873  {
2874  wfsBeta<shwfs<realT,iosT>>(nullptr);
2875  }
2876  else if(wfsStr == "calculatedWFS")
2877  {
2878  wfsBeta<calculatedWFS<realT,iosT>>(nullptr);
2879 
2880  calculatedWFS<realT,iosT> * cwfs = static_cast<calculatedWFS<realT,iosT> *>(m_wfsBeta);
2881  config(cwfs->m_beta_p_file, "aosys.wfs_beta_p");
2882  config(cwfs->m_beta_r_file, "aosys.wfs_beta_r");
2883  bool sens = cwfs->m_sensitivity;
2884  config(sens, "aosys.wfs_sensitivity");
2885  if(config.isSet("aosys.wfs_sensitivity"))
2886  {
2887  cwfs->m_sensitivity = sens;
2888  }
2889  }
2890  else
2891  {
2892  mxThrowException(err::invalidconfig, "aoSystem::loadConfig", "unknown WFS " + wfsStr + " specified");
2893  }
2894  }
2895 
2896  //We load the default value, get the config value (which will be the default if not set), and
2897  //then if it was set, call the setter function so any side effects are captured.
2898 
2899  //diameter
2900  realT nD = D();
2901  config(nD, "aosys.D");
2902  if(config.isSet("aosys.D") ) D(nD);
2903 
2904  //d_min
2905  std::vector<realT> nd_min = d_min();
2906  config(nd_min, "aosys.d_min");
2907  if(config.isSet("aosys.d_min")) d_min(nd_min);
2908 
2909  bool noptd = optd();
2910  config(noptd, "aosys.optd");
2911  if(config.isSet("aosys.optd")) optd(noptd);
2912 
2913  realT noptd_delta =optd_delta();
2914  config(noptd_delta, "aosys.optd_delta");
2915  if(config.isSet("aosys.optd_delta")) optd_delta(noptd_delta);
2916 
2917  realT nlam_wfs = lam_wfs();
2918  config(nlam_wfs, "aosys.lam_wfs");
2919  if(config.isSet("aosys.lam_wfs") ) lam_wfs(nlam_wfs);
2920 
2921  //npix_wfs
2922  std::vector<realT> nnpix_wfs = npix_wfs();
2923  config(nnpix_wfs, "aosys.npix_wfs");
2924  if(config.isSet("aosys.npix_wfs")) npix_wfs(nnpix_wfs);
2925 
2926  //ron_wfs
2927  std::vector<realT> nron_wfs = ron_wfs();
2928  config(nron_wfs, "aosys.ron_wfs");
2929  if(config.isSet("aosys.ron_wfs")) ron_wfs(nron_wfs);
2930 
2931  //Fbg
2932  std::vector<realT> nFbg = Fbg();
2933  config(nFbg, "aosys.Fbg");
2934  if(config.isSet("aosys.Fbg")) Fbg(nFbg);
2935 
2936  //minTauWFS
2937  std::vector<realT> nminTauWFS = minTauWFS();
2938  config(nminTauWFS, "aosys.minTauWFS");
2939  if(config.isSet("aosys.minTauWFS")) minTauWFS(nminTauWFS);
2940 
2941  //bin_npix
2942  bool nbin_npix = bin_npix();
2943  config(nbin_npix, "aosys.bin_npix");
2944  if(config.isSet("aosys.bin_npix")) bin_npix(nbin_npix);
2945 
2946  //tauWFS
2947  realT ntauWFS = tauWFS();
2948  config( ntauWFS, "aosys.tauWFS");
2949  if(config.isSet("aosys.tauWFS")) tauWFS(ntauWFS);
2950 
2951  //deltaTau
2952  realT ndeltaTau = deltaTau();
2953  config( ndeltaTau, "aosys.deltaTau");
2954  if(config.isSet("aosys.deltaTau")) deltaTau(ndeltaTau);
2955 
2956  //optTau
2957  bool noptTau = optTau();
2958  config(noptTau, "aosys.optTau");
2959  if(config.isSet("aosys.optTau")) optTau(noptTau);
2960 
2961  //lam_sci
2962  realT nlam_sci = lam_sci();
2963  config( nlam_sci, "aosys.lam_sci");
2964  if(config.isSet("aosys.lam_sci") ) lam_sci( nlam_sci );
2965 
2966  //zeta
2967  realT nzeta = zeta();
2968  config(nzeta , "aosys.zeta");
2969  if(config.isSet("aosys.zeta") ) zeta(nzeta);
2970 
2971  //fit_mn_max
2972  realT fmnm = fit_mn_max();
2973  config( fmnm, "aosys.fit_mn_max");
2974  if(config.isSet("aosys.fit_mn_max") ) fit_mn_max(fmnm);
2975 
2976  //circularLimit
2977  bool cl = circularLimit();
2978  config(cl, "aosys.circularLimit");
2979  if(config.isSet("aosys.circularLimit") ) circularLimit(cl);
2980 
2981  //spatialFilter_ku
2982  realT ku = spatialFilter_ku();
2983  config( ku, "aosys.spatialFilter_ku");
2984  if(config.isSet("aosys.spatialFilter_ku") ) spatialFilter_ku(ku);
2985 
2986  //spatialFilter_kv
2987  realT kv = spatialFilter_kv();
2988  config( kv, "aosys.spatialFilter_kv");
2989  if(config.isSet("aosys.spatialFilter_kv") ) spatialFilter_kv(kv);
2990 
2991  //ncp_wfe
2992  realT nwfe = ncp_wfe();
2993  config( nwfe, "aosys.ncp_wfe");
2994  if(config.isSet("aosys.ncp_wfe") ) ncp_wfe(nwfe);
2995 
2996  //ncp_alpha
2997  realT na = ncp_alpha();
2998  config( na, "aosys.ncp_alpha");
2999  if(config.isSet("aosys.ncp_alpha") ) ncp_alpha( na );
3000 
3001  //F0
3002  realT nF0 = F0();
3003  config(nF0, "aosys.F0");
3004  if(config.isSet("aosys.F0") ) F0(nF0);
3005 
3006  //star_mag
3007  realT smag = starMag();
3008  config( smag, "aosys.starMag");
3009  if(config.isSet("aosys.starMag") ) starMag( smag );
3010 
3011  atm.loadConfig(config);
3012  psd.loadConfig(config);
3013 }
3014 
3015 extern template
3016 class aoSystem<float, vonKarmanSpectrum<float>, std::ostream>;
3017 
3018 extern template
3019 class aoSystem<double, vonKarmanSpectrum<double>, std::ostream>;
3020 
3021 extern template
3023 
3024 #ifdef HASQUAD
3025 extern template
3027 #endif
3028 
3029 
3030 
3031 } //namespace analysis
3032 } //namespace AO
3033 } //namespace mx
3034 
3035 #endif //aoSystem_hpp
Provides a class to specify atmosphere parameters.
Calculate and provide constants related to adaptive optics.
Spatial power spectra used in adaptive optics.
Definitions of various analytic wavefront sensors.
Describes an analytic adaptive optics (AO) system.
Definition: aoSystem.hpp:68
bool circularLimit()
Get the value of the circularLimit flag.
Definition: aoSystem.hpp:1718
realT m_ncp_wfe
Static WFE [m rms].
Definition: aoSystem.hpp:122
void loadMagAOX()
Load parameters corresponding to the MagAO-X system.
Definition: aoSystem.hpp:1213
bool bin_npix()
Get the value of the pixel binngin flag.
Definition: aoSystem.hpp:1605
void loadGuyon2005()
Load the default parameters from Guyon, 2005 .
Definition: aoSystem.hpp:1189
realT m_optd_delta
The fractional change from d_min used in optimization. Set to 1 for integer binnings,...
Definition: aoSystem.hpp:87
bool optd()
Get the value of m_optd.
Definition: aoSystem.hpp:1316
void C1Map(imageT &map, bool normStrehl)
Calculate a 2D map of contrast C1.
Definition: aoSystem.hpp:2554
realT m_wfeNCP
Total WFE due to NCP errors [rad^2 at m_lam_sci].
Definition: aoSystem.hpp:141
realT F0()
Get the value of the 0 magnitude photon rate.
Definition: aoSystem.hpp:1788
realT C5(realT m, realT n, bool normStrehl=true)
Calculate the contrast due to scintilation-amplitude chromaticity.
Definition: aoSystem.hpp:2659
realT chromScintOPDErrorTotal()
Calculate the wavefront error due to scintillation chromaticity in the OPD over all spatial frequenci...
Definition: aoSystem.hpp:1935
void C5Map(imageT &map, bool normStrehl)
Calculate a 2D map of contrast C5.
Definition: aoSystem.hpp:2669
realT C1(realT m, realT n, bool normStrehl=true)
Calculate the contrast due to uncorrected amplitude, C1.
Definition: aoSystem.hpp:2544
realT C0var(realT m, realT n)
Calculate the residual variance due to uncorrected phase at a spatial frequency.
Definition: aoSystem.hpp:2504
realT C_(int m, int n, bool normStrehl, varFuncT varFunc, int doFittingError)
Worker function for raw contrast fuctions.
Definition: aoSystem.hpp:2432
realT m_wfeVar
The WFE variance, in meters^2. Never use this directly, instead use wfeVar().
Definition: aoSystem.hpp:143
realT d_opt()
Calculate the optimum actuator spacing.
Definition: aoSystem.hpp:2110
std::vector< realT > d_min()
Get the minimum subaperture sampling for all WFS modes.
Definition: aoSystem.hpp:1302
realT ncpError()
Calculate the total NCP variance in rad^2.
Definition: aoSystem.hpp:2274
realT spatialFilter_kv()
Get the value of spatialFilter_kv.
Definition: aoSystem.hpp:1746
bool m_specsChanged
Flag to indicate that a specification has changed.
Definition: aoSystem.hpp:129
bool m_circularLimit
Flag to indicate that the spatial frequency limit is circular, not square.
Definition: aoSystem.hpp:117
realT zeta()
Get the zenith angle.
Definition: aoSystem.hpp:1685
realT Fg()
Get the photon rate at the current Star magnitude.
Definition: aoSystem.hpp:1814
const Eigen::Array< bool, -1, -1 > & controlledModes()
Access the array of controlledModes.
Definition: aoSystem.hpp:1820
std::vector< realT > minTauWFS()
Get the values of the minimum WFS exposure time.
Definition: aoSystem.hpp:1588
std::vector< realT > m_npix_wfs
Number of WFS pixels. One per WFS mode.
Definition: aoSystem.hpp:95
void calcStrehl()
Calculate the component WFE, total WFE, and Strehl ratio.
Definition: aoSystem.hpp:2338
realT lam_sci()
Get the science wavelength.
Definition: aoSystem.hpp:1669
realT m_wfeFitting
Total WFE due to fitting error [rad^2 at m_lam_sci].
Definition: aoSystem.hpp:136
realT m_wfeChromScintOPD
Total WFE due to the chromaticity of scintillation OPD [rad^2 at lam_sc].
Definition: aoSystem.hpp:137
realT m_strehl
Strehl ratio, a calculated quantity. Never use this directdy, instead use strehl().
Definition: aoSystem.hpp:144
realT deltaTau()
Get the value of m_deltaTau.
Definition: aoSystem.hpp:1641
realT wfeVar()
Get the current value of the total WFE variance.
Definition: aoSystem.hpp:2415
realT ncp_wfe()
Get the value of the non-common path WFE.
Definition: aoSystem.hpp:1760
realT m_spatialFilter_ku
The spatial filter cutoff in u, [m^-1].
Definition: aoSystem.hpp:119
realT tauWFS()
Get the value of the minimum WFS exposure time.
Definition: aoSystem.hpp:1627
std::vector< realT > m_ron_wfs
WFS readout noise [electrons/pix]. One per WFS mode.
Definition: aoSystem.hpp:96
bool m_ownWfsBeta
Flag indicating if the WFS beta_p pointer is owned by this instance.
Definition: aoSystem.hpp:90
realT m_secZeta
Secant of the Zenith angle (calculated)
Definition: aoSystem.hpp:113
realT m_starMag
The magnitude of the star.
Definition: aoSystem.hpp:127
realT C4(realT m, realT n, bool normStrehl=true)
Calculate the contrast due to scintilation-OPD chromaticity.
Definition: aoSystem.hpp:2628
realT timeDelayError(realT m, realT n, realT d, int b)
Calculate the time delay at a spatial frequency at the optimum exposure time and the specified actuat...
Definition: aoSystem.hpp:1880
realT chromIndexErrorTotal()
Calculate the wavefront error due to chromaticity in the index of refraction at a specific spatial fr...
Definition: aoSystem.hpp:1976
realT chromIndexError(int m, int n)
Calculate the wavefront error due to chromaticity in the index of refraction at a given spatial frequ...
Definition: aoSystem.hpp:1968
realT m_d_opt
Current optimum AO system actuator pitch [m].
Definition: aoSystem.hpp:85
realT C4var(realT m, realT n)
Calculate the residual variance due to scintilation-OPD chromaticity.
Definition: aoSystem.hpp:2615
realT m_ncp_alpha
Power-law exponent for the NCP aberations. Default is 2.
Definition: aoSystem.hpp:123
bool m_optTau
Flag controlling whether optimum integration time is calculated (true) enforcing m_minTauWFS,...
Definition: aoSystem.hpp:108
realT beta_r(realT m, realT n)
Get the value of beta_r for a spatial frequency.
Definition: aoSystem.hpp:1386
realT spatialFilter_ku()
Get the value of spatialFilter_ku.
Definition: aoSystem.hpp:1732
realT m_spatialFilter_kv
The spatial filter cutoff in v, [m^-1].
Definition: aoSystem.hpp:120
void C7Map(imageT &map, bool normStrehl)
Calculate a 2D map of contrast C7.
Definition: aoSystem.hpp:2728
realT C7var(realT m, realT n)
Calculate the residual variance due to dispersive anisoplanatism.
Definition: aoSystem.hpp:2707
realT fittingErrorTotal()
Calculate the total fitting error over all uncorrected spatial frequencies.
Definition: aoSystem.hpp:1920
bool m_bin_npix
Flag controlling whether or not to bin WFS pixels according to the actuator spacing.
Definition: aoSystem.hpp:100
void C0Map(imageT &map, bool normStrehl)
Calculate a 2D map of contrast C0.
Definition: aoSystem.hpp:2525
bool optTau()
Get the value of m_optTau.
Definition: aoSystem.hpp:1655
int m_bin_opt
The optimum binning factor. If WFS modes are used, this is the mode index (0 to N-1)....
Definition: aoSystem.hpp:102
realT m_tauWFS
Actual WFS exposure time [sec].
Definition: aoSystem.hpp:104
realT beta_p(realT m, realT n)
Get the value of beta_p for a spatial frequency.
Definition: aoSystem.hpp:1378
std::vector< realT > m_minTauWFS
Minimum WFS exposure time [sec]. One per WFS mode.
Definition: aoSystem.hpp:98
realT C5var(realT m, realT n)
Calculate the residual variance due to to scintilation-amplitude chromaticity.
Definition: aoSystem.hpp:2646
wfs< realT, iosT > * m_wfsBeta
The WFS beta_p class.
Definition: aoSystem.hpp:89
realT secZeta()
Get the zecant of the zenith angle.
Definition: aoSystem.hpp:1691
realT measurementError(realT m, realT n, realT d, int b)
Calculate the measurement noise at a spatial frequency and specified actuator spacing.
Definition: aoSystem.hpp:1849
realT dispAnisoOPDErrorTotal()
Calculate the wavefront error due to dispersive anisoplanatism in the OPD over all specific spatial f...
Definition: aoSystem.hpp:1991
realT m_lam_wfs
WFS wavelength [m].
Definition: aoSystem.hpp:92
void C3Map(imageT &map, bool normStrehl)
Calculate a 2D map of contrast C3.
Definition: aoSystem.hpp:2607
realT m_F0
0 mag flux from star at WFS [photons/sec]
Definition: aoSystem.hpp:125
realT C2var(realT m, realT n)
Calculate the residual variance due to measurement and time delay errors in phase/OPD at a spatial fr...
Definition: aoSystem.hpp:2562
Eigen::Array< bool,-1,-1 > m_controlledModes
Map of which modes are under control. Set by calcStrehl.
Definition: aoSystem.hpp:132
bool m_dminChanged
Flag to indicate that d_min has changed.
Definition: aoSystem.hpp:130
bool m_optd
Flag controlling whether actuator pitch is optimized (true) or just uses m_d_min (false)....
Definition: aoSystem.hpp:86
std::vector< realT > Fbg()
Get the value of the background flux for all WFS modes.
Definition: aoSystem.hpp:1542
realT timeDelayErrorTotal()
Calculate the time delay error over all corrected spatial frequencies.
Definition: aoSystem.hpp:1902
realT dispAnisoOPDError(int m, int n)
Calculate the wavefront error due to dispersive anisoplanatism in the OPD at a given spatial frequenc...
Definition: aoSystem.hpp:1983
realT m_zeta
Zenith angle [radians].
Definition: aoSystem.hpp:112
realT signal2Noise2(realT &Nph, realT tau_wfs, realT d, int b)
Calculate the terms of the signal to noise ratio squared (S/N)^2 for the WFS measurement.
Definition: aoSystem.hpp:1826
realT C3var(realT m, realT n)
Calculate the residual variance due to measurement and time delay errors in amplitude at a spatial fr...
Definition: aoSystem.hpp:2589
realT starMag()
Get the value of the Star's magnitude.
Definition: aoSystem.hpp:1802
void loadGMagAOX()
Load parameters corresponding to the G-MagAO-X system.
Definition: aoSystem.hpp:1236
realT m_D
Telescope diameter [m].
Definition: aoSystem.hpp:81
realT chromScintAmpError()
Calculate the wavefront error due to scintillation chromaticity in amplitude over all spatial frequen...
std::vector< realT > ron_wfs()
Get the value of the WFS readout noise for all WFS modes.
Definition: aoSystem.hpp:1496
std::vector< realT > npix_wfs()
Get the number of pixels in the WFS for all WFS modes.
Definition: aoSystem.hpp:1449
realT C7(realT m, realT n, bool normStrehl=true)
Calculate the contrast due to dispersive anisoplanatism.
Definition: aoSystem.hpp:2718
realT measurementErrorTotal()
Calculate the total measurement error over all corrected spatial frequencies.
Definition: aoSystem.hpp:1873
void setupConfig(app::appConfigurator &config)
Setup the configurator to configure this class.
Definition: aoSystem.hpp:2812
realT strehl()
Get the current Strehl ratio.
Definition: aoSystem.hpp:2423
realT C0(realT m, realT n, bool normStrehl=true)
Calculate the contrast due to uncorrected phase, C0.
Definition: aoSystem.hpp:2514
realT C1var(realT m, realT n)
Calculate the residual variance due to uncorrected amplitude at a spatial frequency.
Definition: aoSystem.hpp:2533
realT ncp_alpha()
Get the value of the non-common path WFE PSD index.
Definition: aoSystem.hpp:1774
realT m_wfeTimeDelay
Total WFE due to time delay [rad^2 at m_lam_sci].
Definition: aoSystem.hpp:135
realT chromScintOPDError(int m, int n)
Calculate the wavefront error due to scintillation chromaticity in the OPD at a spatial frequency.
Definition: aoSystem.hpp:1927
void C_Map(imageT &im, CfuncT Cfunc, bool normStrehl)
Worker function for the contrast-map functions.
Definition: aoSystem.hpp:2479
int m_fit_mn_max
Maximum spatial frequency index to use for fitting error calculation.
Definition: aoSystem.hpp:115
iosT & dumpAOSystem(iosT &ios)
Output current parameters to a stream.
Definition: aoSystem.hpp:2736
std::vector< realT > m_Fbg
Background flux, [photons/sec/pixel]. One per WFS mode.
Definition: aoSystem.hpp:97
void C4Map(imageT &map, bool normStrehl)
Calculate a 2D map of contrast C4.
Definition: aoSystem.hpp:2638
realT C6var(realT m, realT n)
Calculate the residual variance due to chromaticity of the index of refraction of air.
Definition: aoSystem.hpp:2677
realT C2(realT m, realT n, bool normStrehl=true)
Calculate the contrast due to measurement and time delay errors in phase/OPD at a spatial frequency.
Definition: aoSystem.hpp:2571
realT m_wfeMeasurement
Total WFE due to measurement a error [rad^2 at m_lam_sci].
Definition: aoSystem.hpp:134
void C2Map(imageT &map, bool normStrehl)
Calculate a 2D map of contrast C2().
Definition: aoSystem.hpp:2581
realT dispAnisoAmpError()
Calculate the wavefront error due to dispersive anisoplanatism in the amplitude at a specific spatial...
Definition: aoSystem.hpp:1998
std::vector< realT > m_d_min
Minimum AO system actuator pitch [m]. One per WFS mode.
Definition: aoSystem.hpp:83
void loadConfig(app::appConfigurator &config)
Load the configuration of this class from a configurator.
Definition: aoSystem.hpp:2852
realT C6(realT m, realT n, bool normStrehl=true)
Calculate the contrast due to chromaticity of the index of refraction of air.
Definition: aoSystem.hpp:2689
int fit_mn_max()
Get the value of m_fit_mn_max.
Definition: aoSystem.hpp:1704
int bin_opt()
Get the value of the optimum binning factor/index.
Definition: aoSystem.hpp:1611
realT m_wfeChromIndex
Total WFE due to the chromaticity of the index of refraction [rad^2 at lam_Sci].
Definition: aoSystem.hpp:138
realT m_lam_sci
Science wavelength [m].
Definition: aoSystem.hpp:110
realT optimumTauWFS(realT m, realT n, realT d, int b)
Calculate the optimum exposure time for a given spatial frequency at a specified actuator spacing.
Definition: aoSystem.hpp:2027
aoSystem()
Default c'tor.
Definition: aoSystem.hpp:1174
realT m_deltaTau
Loop latency [sec].
Definition: aoSystem.hpp:106
void C6Map(imageT &map, bool normStrehl)
Calculate a 2D map of contrast C6.
Definition: aoSystem.hpp:2699
realT lam_wfs()
Get the value of the WFS wavelength.
Definition: aoSystem.hpp:1403
realT D()
Get the value of the primary mirror diamter.
Definition: aoSystem.hpp:1261
realT m_wfeAnisoOPD
Total WFE due to dispersive anisoplanatism OPD.
Definition: aoSystem.hpp:139
realT C3(realT m, realT n, bool normStrehl=true)
Calculate the contrast due to measurement and time delay errors in amplitude at a spatial frequency.
Definition: aoSystem.hpp:2597
realT fittingError(realT m, realT n)
Calculate the fitting error at a specific spatial frequency.
Definition: aoSystem.hpp:1910
wfs< realT, iosT > * wfsBeta()
Get the WFS Beta pointer.
Definition: aoSystem.hpp:1372
realT optd_delta()
Get the value of the fractional change in actuator spacing for optimization..
Definition: aoSystem.hpp:1330
mxException for invalid config settings
mxException for parameters which aren't set
mxException for a size error
constexpr units::realT c()
The speed of light.
Definition: constants.hpp:60
constexpr units::realT k()
Boltzmann Constant.
Definition: constants.hpp:71
void quarticRoots(std::vector< std::complex< realT > > &x, realT a, realT b, realT c, realT d, realT e)
Find the roots of the general quartic equation.
Definition: roots.hpp:129
The mxlib c++ namespace.
Definition: mxError.hpp:107
iosT & dumpGitStatus(iosT &ios)
Dump the current git status of the library to a stream.
Definition: mxlib.hpp:50
The calculated WFS uses sensitivities provided by FITS files.
Definition: aoWFS.hpp:283
The ideal wavefront sensor sensitivity function.
Definition: aoWFS.hpp:39
Class to manage a set of configurable values, and read their values from config/ini files and the com...
void add(const configTarget &tgt)
Add a configTarget.
bool isSet(const std::string &name, std::unordered_map< std::string, configTarget > &targets)
Check if a target has been set by the configuration.