mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
directPhaseSensor.hpp
Go to the documentation of this file.
1 /** \file directPhaseSensor.hpp
2  * \author Jared R. Males (jaredmales@gmail.com)
3  * \brief Declaration and definition of a direct phase sensor.
4  * \ingroup mxAO_sim_files
5  *
6  */
7 
8 #ifndef directPhaseSensor_hpp
9 #define directPhaseSensor_hpp
10 
11 #include "../../math/randomT.hpp"
12 
13 #include "../../ioutils/fits/fitsFile.hpp"
14 #include "../../improc/eigenCube.hpp"
15 
16 //#include <mx/fraunhoferImager.hpp>
17 #include "../../sigproc/psdFilter.hpp"
18 
19 #include "wavefront.hpp"
20 
21 
22 #ifdef DEBUG
23 #define BREAD_CRUMB std::cout << "DEBUG: " << __FILE__ << " " << __LINE__ << "\n";
24 #else
25 #define BREAD_CRUMB
26 #endif
27 
28 
29 namespace mx
30 {
31 namespace AO
32 {
33 namespace sim
34 {
35 
36 
37 template<typename _realT>
38 struct wfsImageT
39 {
40  typedef _realT realT;
41 
42  realT iterNo;
43 
44  ///The wavefront sensor detector image type
45  typedef Eigen::Array< realT, Eigen::Dynamic, Eigen::Dynamic> imageT;
46 
47  imageT image;
48 };
49 
50 
51 template<typename _realT, typename _detectorT>
52 class directPhaseSensor
53 {
54 public:
55  typedef _realT realT;
56 
57  typedef std::complex<_realT> complexT;
58 
59  ///The wavefront data type
60  typedef wavefront<_realT> wavefrontT;
61 
62  ///The pupil type
63  typedef improc::eigenImage<realT> pupilT;
64 
65  ///The wavefront complex field type
66  typedef mx::wfp::imagingArray<std::complex<_realT>,mx::wfp::fftwAllocator<std::complex<_realT> >, 0> complexFieldT;
67 
68  typedef _detectorT detectorT;
69 
70 
72 
73  ///Alias for a poisson random variate
75 
76 
77 protected:
78 
79  /* Standard WFS Interface: */
80  int m_wfSz {0}; ///< Size of the wavefront in pixels
81 
82  int m_detRows {0}; ///<The number of rows of the WFS m_detector. After forming the image the WFS detector plane is re-binned to this.
83  int m_detCols {0}; ///<The number of columns of the WFS m_detector. After forming the image the WFS detector plane is re-binned to this.
84 
85  realT m_lambda {0}; ///< Central wavelength, in meters
86 
87  int m_iTime {0}; ///<Integration time in loop steps
88 
89  int m_roTime {1}; ///<Readout time in loop steps
90 
91  realT m_simStep {0.001}; ///<The simulation stepsize in seconds.
92 
93 
94  /* Direct Phase Sensor specific: */
95 
96  realT m_npix {0}; ///< The number of pixels assumed actually used for WFS in the S/N calc.
97  realT m_Fbg {0.0}; ///< The background flux in photons/sec/pixel.
98 
99  int m_iTime_counter {0};
100 
101  int m_reading {0};
102 
103  int m_roTime_counter {0};
104 
105  bool m_firstRun {true};
106 
107  std::vector<wavefrontT> m_wavefronts;
108 
109  int m_lastWavefront;
110 
111  ///The image formed by the WFS
112  wfsImageT<realT> m_wfsImage;
113 
114 public:
115  bool m_poissonNoise {true};
116 
117  ///Default c'tor
118  directPhaseSensor();
119 
120  /* The standard WFS interface: */
121 
122  detectorT m_detector;
123 
124  ///The image on the detector, resized from wfsImage
125  wfsImageT<realT> m_detectorImage;
126 
127  ///Get the wavefront size in pixels
128  /**
129  * \returns the wavefront size in pixels
130  */
131  int wfSz();
132 
133  ///Set the wavefront size in pixels.
134  void wfSz( int sz /**< [in] The new size */);
135 
136  ///Get the detector rows in pixels
137  /**
138  * \returns m_detRows
139  */
140  int detRows();
141 
142  ///Set the detector rows in pixels.
143  /**
144  * \param sz is the new size
145  */
146  void detRows(int sz);
147 
148  ///Get the detector Cols in pixels
149  /**
150  * \returns m_detCols
151  */
152  int detCols();
153 
154  ///Set the detector columns in pixels.
155  /**
156  * \param sz is the new size
157  */
158  void detCols(int sz);
159 
160  ///Set the detector columns in pixels.
161  /**
162  * \param sz is the new size
163  */
164  void detSize(int nrows, int ncols);
165 
166  ///Get the PyWFS central wavelength
167  /**
168  * \returns the central wavelength in meters
169  */
170  realT lambda();
171 
172  ///Set the PyWFS central wavelength
173  /**
174  * \param d is the new central wavelength in meters
175  */
176  void lambda(realT l);
177 
178 
179  ///Get the PyWFS integration time, in time steps
180  int iTime();
181 
182  ///Set the PyWFS integration time, in time steps
183  void iTime(int it);
184 
185  ///Get the PyWFS detector readout time, in time steps
186  int roTime();
187 
188  ///Set the PyWFS detector readout time, in time steps
189  void roTime(int rt);
190 
191  ///Get the simulation step-size, in seconds.
192  realT simStep();
193 
194  ///Set the simulation step-size, in seconds.
195  void simStep(realT st);
196 
197  ///Get the number of pixels used for noise calculations
198  /**
199  * \returns the number of pixels used by the wfs, m_npix.
200  */
201  realT npix();
202 
203  ///Set the number of pixels used fo rnoise calculations
204  /**
205  */
206  void npix( realT np /**< [in] the number of pixels to be used by the WFS*/);
207 
208  ///Get the background rate
209  /**
210  * \returns the background rate in photons/pixel/sec, the current value of m_Fbg.
211  */
212  realT Fbg();
213 
214  ///Set the background rate
215  /**
216  */
217  void Fbg( realT bg /**< [in] the background rate in photons/pixel/sec.*/);
218 
219  template<typename AOSysT>
220  void linkSystem(AOSysT & AOSys);
221 
222  ///Record a wavefront without sensing
223  /** This merely inserts the wavefront in the circular buffer but does no other processing
224  * Retruns 0 on success
225  */
226  int recordWavefront(wavefrontT & pupilPlane);
227 
228  ///Sense the wavefront aberrations
229  /** Returns true if a new wavefront measurement is ready.
230  * Retruns false if still integrating.
231  */
232  bool senseWavefront(wavefrontT & pupilPlane);
233 
234  ///Sense the wavefront aberrations in a calibration mode
235  /** Allows for faster calibrations.
236  */
237  bool senseWavefrontCal(wavefrontT & pupilPlane);
238 
239  void doSenseWavefront();
240 
241  /** \name Spatial Filtering
242  * @{
243  */
244 protected:
245  bool m_applyFilter {false}; ///< Flag to control whether or not the spatial filter is applied.
246 
247  int m_filterWidth {0}; ///< The half-width of the filter, in Fourier domain pixels corresponding to 1/D spatial frequency units.
248 
249  sigproc::psdFilter<realT,2> m_filter; ///< The spatial filter class object.
250 
251 public:
252 
253  /// Set the flag controlling whether or not the spatial filter is applied
254  void applyFilter(bool af /**< [in] true to apply the filter, false to not apply*/);
255 
256  /// Get the current value of the flag controlling whether or not the spatial filter is applied
257  /**
258  * \returns the current value of m_applyFilter
259  */
260  bool applyFilter();
261 
262  /// Set the spatial filter half-width
263  /** This sets up the filter and loads it into m_filter. The filter is a hard-edged square of width 2*width+1 pixels in the Fourier plane.
264  *
265  * m_filterWidth must still be set to true after calling this function.
266  */
267  void filterWidth( int width /**< [in] the desired half-width of the filter*/);
268 
269  /// Get the current value of the filter half-width
270  /**
271  * \returns the current value of m_filterWidth
272  */
273  int filterWidth();
274 
275  /// Provides access to the filter for use by other parts of the simulation.
276  /**
277  * \returns a const reference to m_filter.
278  */
279  const sigproc::psdFilter<realT, 2> & filter();
280 
281  ///@}
282 
283  /** \name Photon Noise
284  * To turn on the addition of photon noise to the WFS image, you must set beta_p to be greater than 0,
285  * and must supply the pupil image.
286  *
287  * @{
288  */
289 protected:
290 
291  norm_distT m_normVar; ///< Gets normal-distributed variates
292  poisson_distT m_poissonVar;
293 
294 
295  /// The photon noise senstivity parameter.
296  /** If 0 (default) no noise is applied. A value of 1 represents the ideal interferomter.
297  * Note that this is constant vs. spatial frequency. See Guyon (2005) \cite guyon_2005 for more information about \f$ \beta_p \f$.
298  */
299  realT m_beta_p {0};
300 
301  /// The pupil is needed to properly normalize poisson noise.
302  /** If null, then no noise will be applied.
303  */
304  pupilT * m_pupil {nullptr};
305 
306  /// Array used internally to calculated noise, global to avoid re-allocations.
307  typename wfsImageT<realT>::imageT m_noiseIm;
308 
309 public:
310 
311  /// Set the new value of the photon noise sensitivity parameter, beta_p.
312  void beta_p(realT bp /**< [in] the new value of beta_p */);
313 
314  /// Get the current value of the photon noise sensitivity parameter.
315  /**
316  * \returns the current value of m_beta_p.
317  */
318  realT beta_p();
319 
320  /// Set the pupil
321  /** Sets the m_pupil pointer to the value provided.
322  */
323  void pupil(pupilT * pupil /**< [in] pointer to the pupil image */);
324 
325  /// Set the pupil
326  /** Sets the m_pupil pointer to the address of the image provided.
327  */
328  void pupil(pupilT & pupil /**< [in] the pupil image */);
329 
330  /// Get the current pupil as a pointer
331  /**
332  * \returns the current value of m_pupil
333  */
334  pupilT * pupil();
335 
336  ///@}
337 };
338 
339 template<typename _realT, typename _detectorT>
340 directPhaseSensor<_realT, _detectorT>::directPhaseSensor()
341 {
342  iTime(1);
343 
344  m_normVar.seed();
345  m_poissonVar.seed();
346 }
347 
348 
349 template<typename _realT, typename _detectorT>
350 int directPhaseSensor<_realT, _detectorT>::wfSz()
351 {
352  return m_wfSz;
353 }
354 
355 template<typename _realT, typename _detectorT>
356 void directPhaseSensor<_realT, _detectorT>::wfSz(int sz)
357 {
358  if( m_wfSz == sz) return;
359 
360  m_wfSz = sz;
361 }
362 
363 template<typename _realT, typename _detectorT>
364 int directPhaseSensor<_realT, _detectorT>::detRows()
365 {
366  return m_detRows;
367 }
368 
369 template<typename _realT, typename _detectorT>
370 int directPhaseSensor<_realT, _detectorT>::detCols()
371 {
372  return m_detCols;
373 }
374 
375 template<typename _realT, typename _detectorT>
376 void directPhaseSensor<_realT, _detectorT>::detSize(int nrows, int ncols)
377 {
378  if( m_detRows == nrows && m_detCols == ncols) return;
379 
380  m_detRows = nrows;
381  m_detCols = ncols;
382 
383  m_detector.setSize(m_detRows, m_detCols);
384  m_detectorImage.image.resize(m_detRows, m_detCols);
385 
386 
387 }
388 
389 template<typename _realT, typename _detectorT>
390 _realT directPhaseSensor<_realT, _detectorT>::lambda()
391 {
392  return m_lambda;
393 }
394 
395 template<typename _realT, typename _detectorT>
396 void directPhaseSensor<_realT, _detectorT>::lambda(_realT l)
397 {
398  m_lambda = l;
399 }
400 
401 template<typename _realT, typename _detectorT>
402 template<typename AOSysT>
403 void directPhaseSensor<_realT, _detectorT>::linkSystem(AOSysT & AOSys)
404 {
405  static_cast<void>(AOSys);
406 }
407 
408 template<typename _realT, typename _detectorT>
409 int directPhaseSensor<_realT, _detectorT>::iTime()
410 {
411  return m_iTime;
412 }
413 
414 template<typename _realT, typename _detectorT>
415 void directPhaseSensor<_realT, _detectorT>::iTime(int it)
416 {
417  if(it < 1)
418  {
419  std::cerr << "iTime must be >= 1. Correcting\n";
420  it = 1;
421  }
422 
423  m_iTime = it;
424 
425  m_wavefronts.resize(m_iTime+2+100);
426  m_lastWavefront = -1;
427 
428  m_detector.expTime(m_simStep*m_iTime);
429 
430 }
431 
432 template<typename _realT, typename _detectorT>
433 int directPhaseSensor<_realT, _detectorT>::roTime()
434 {
435  return roTime;
436 }
437 
438 template<typename _realT, typename _detectorT>
439 void directPhaseSensor<_realT, _detectorT>::roTime(int rt)
440 {
441  if(rt < 1)
442  {
443  std::cerr << "roTime must be >= 1. Correcting\n";
444  rt = 1;
445  }
446 
447  m_roTime = rt;
448 
449 
450 }
451 
452 template<typename _realT, typename _detectorT>
453 _realT directPhaseSensor<_realT, _detectorT>::simStep()
454 {
455  return simStep;
456 }
457 
458 template<typename _realT, typename _detectorT>
459 void directPhaseSensor<_realT, _detectorT>::simStep(_realT st)
460 {
461 
462  m_simStep = st;
463 
464  m_detector.expTime(m_simStep*m_iTime);
465 
466 
467 }
468 
469 template<typename realT, typename _detectorT>
470 realT directPhaseSensor<realT, _detectorT>::npix()
471 {
472  return m_npix;
473 }
474 
475 template<typename realT, typename _detectorT>
476 void directPhaseSensor<realT, _detectorT>::npix( realT np )
477 {
478  m_npix = np;
479 }
480 
481 template<typename realT, typename _detectorT>
482 realT directPhaseSensor<realT, _detectorT>::Fbg()
483 {
484  return m_Fbg;
485 }
486 
487 template<typename realT, typename _detectorT>
488 void directPhaseSensor<realT, _detectorT>::Fbg( realT bg)
489 {
490  m_Fbg = bg;
491 }
492 
493 template<typename _realT, typename _detectorT>
494 int directPhaseSensor<_realT, _detectorT>::recordWavefront(wavefrontT & pupilPlane)
495 {
496 
497  ++m_lastWavefront;
498  if((size_t) m_lastWavefront >= m_wavefronts.size()) m_lastWavefront = 0;
499 
500 
501  wavefrontT pPlane = pupilPlane;
502 
503  m_wavefronts[m_lastWavefront].amplitude = pPlane.amplitude;
504  m_wavefronts[m_lastWavefront].phase = pPlane.phase;
505  m_wavefronts[m_lastWavefront].iterNo = pPlane.iterNo;
506 
507  return 0;
508 }
509 
510 
511 template<typename _realT, typename _detectorT>
512 bool directPhaseSensor<_realT, _detectorT>::senseWavefront(wavefrontT & pupilPlane)
513 {
514  using poisson_param_t = typename std::poisson_distribution<long>::param_type;
515 
516  ++m_lastWavefront;
517  if((size_t) m_lastWavefront >= m_wavefronts.size()) m_lastWavefront = 0;
518 
519 
520  wavefrontT pPlane = pupilPlane;
521 
522  m_wavefronts[m_lastWavefront].amplitude = pPlane.amplitude;
523  m_wavefronts[m_lastWavefront].phase = pPlane.phase;
524  m_wavefronts[m_lastWavefront].iterNo = pPlane.iterNo;
525 
526  //std::cerr << m_lastWavefront << " " << pPlane.iterNo << "\n";
527  //Always skip the first one for averaging to center of iTime.
528  if(m_firstRun)
529  {
530  m_firstRun = false;
531  return false;
532  }
533 
534  ++m_iTime_counter;
535 
536 
537  bool rv = false;
538 
539  if(0)//m_reading)
540  {
541  ++m_roTime_counter;
542 
543  if(m_roTime_counter >= m_roTime)
544  {
545  m_detectorImage.image = m_wfsImage.image.block( 0.5*(m_wfsImage.image.rows()-1) - 0.5*(m_detectorImage.image.rows()-1), 0.5*(m_wfsImage.image.cols()-1) - 0.5*(m_detectorImage.image.cols()-1), m_detectorImage.image.rows(), m_detectorImage.image.cols());
546 
547  m_detectorImage.iterNo = m_wfsImage.iterNo;
548 
549  m_roTime_counter = 0;
550  m_reading=0;
551  rv = true;
552  }
553  }
554 
555  if( m_iTime_counter >= m_iTime)
556  {
557  doSenseWavefront();
558 
559  m_iTime_counter = 0;
560 
561  m_reading = 1;
562  m_roTime_counter = 0;
563 
564  //Just do the read
565  m_detectorImage.image = m_wfsImage.image.block( 0.5*(m_wfsImage.image.rows()-1) - 0.5*(m_detectorImage.image.rows()-1), 0.5*(m_wfsImage.image.cols()-1) - 0.5*(m_detectorImage.image.cols()-1), m_detectorImage.image.rows(), m_detectorImage.image.cols());
566 
567  //*** Spatial Filter:
568  if(m_applyFilter)
569  {
570  //std::cerr << "Filtering . . . \n";
571  m_filter.filter(m_detectorImage.image);
572  if(m_pupil != nullptr) m_detectorImage.image *= *m_pupil;
573  }
574 
575 
576  //*** Adding Noise:
577  if(m_beta_p > 0 && m_pupil != nullptr)
578  {
579  m_noiseIm.resize(m_detectorImage.image.rows(), m_detectorImage.image.cols());
580 
581  //Calculate intensity at each pixel
582  for(int c=0;c<m_noiseIm.cols();++c)
583  {
584  for(int r=0;r<m_noiseIm.rows();++r)
585  {
586  m_noiseIm(r,c) = pow(pupilPlane.amplitude(r,c),2)*(*m_pupil)(r,c) * m_detector.expTime();
587  }
588  }
589  //std::cerr << "Total Phots: " << m_noiseIm.sum() << "\n";
590 
591  realT sqrtFbg = sqrt(m_Fbg*m_detector.expTime());
592 
593  //Add noise
594  for(int c=0;c<m_noiseIm.cols();++c)
595  {
596  for(int r=0;r<m_noiseIm.rows();++r)
597  {
598  if(m_noiseIm(r,c) == 0) //assuming branch prediction makes this worth it
599  {
600  continue;
601  }
602  else
603  {
604  realT err = sqrt(m_noiseIm(r,c))*m_normVar;
605  if(sqrtFbg > 0) err += sqrtFbg*m_normVar;
606  if(m_detector.ron() > 0) err += m_detector.ron()*m_normVar;
607 
608  m_detectorImage.image(r,c) += m_beta_p * err/m_noiseIm(r,c); //Fractional noise in photons is noise in radians
609  }
610  }
611  }
612 
613  } //if(m_beta_p > 0 && m_pupil != nullptr)
614 
615 
616  m_detectorImage.iterNo = m_wfsImage.iterNo;
617 
618  m_roTime_counter = 0;
619  m_reading=0;
620  rv = true;
621 
622  }
623 
624  //std::cerr << "DPWFS: " << m_iTime_counter << " " << m_reading << " " << m_roTime_counter << " " << rv << "\n";
625 
626  return rv;
627 
628 }
629 
630 
631 template<typename _realT, typename _detectorT>
632 bool directPhaseSensor<_realT, _detectorT>::senseWavefrontCal(wavefrontT & pupilPlane)
633 {
634 
635  m_lastWavefront = 1;
636 
637  m_wavefronts[0].amplitude = pupilPlane.amplitude;
638  m_wavefronts[0].phase = pupilPlane.phase;
639 
640  m_wavefronts[1].amplitude = pupilPlane.amplitude;
641  m_wavefronts[1].phase = pupilPlane.phase;
642 
643  doSenseWavefront();
644 
645  m_detectorImage.image = m_wfsImage.image.block( 0.5*(m_wfsImage.image.rows()-1) - 0.5*(m_detectorImage.image.rows()-1), 0.5*(m_wfsImage.image.cols()-1) - 0.5*(m_detectorImage.image.cols()-1), m_detectorImage.image.rows(), m_detectorImage.image.cols());
646 
647  if(m_applyFilter)
648  {
649  m_filter.filter(m_detectorImage.image);
650  }
651 
652 
653 
654  return true;
655 
656 }
657 
658 template<typename _realT, typename _detectorT>
659 void directPhaseSensor<_realT, _detectorT>::doSenseWavefront()
660 {
661  wavefrontT pupilPlane;
662 
663  BREAD_CRUMB;
664 
665  /* Here make average wavefront for now */
666  int _firstWavefront = m_lastWavefront - m_iTime;
667  if(_firstWavefront < 0) _firstWavefront += m_wavefronts.size();
668 
669  //std::cerr << m_lastWavefront << " " << m_iTime_counter << " " << _firstWavefront << "\n";
670 
671  pupilPlane.amplitude = 0.5*m_wavefronts[_firstWavefront].amplitude;
672  pupilPlane.phase = 0.5*m_wavefronts[_firstWavefront].phase;
673 
674  pupilPlane.iterNo = 0.5*m_wavefronts[_firstWavefront].iterNo;
675 
676 
677  //std::cerr << "DPS Averaging: " << m_wavefronts[_firstWavefront].iterNo << " " ;
678  BREAD_CRUMB;
679 
680  if(m_wavefronts[_firstWavefront].iterNo < m_iTime)
681  {
682  m_wfsImage.image = pupilPlane.phase;
683  m_wfsImage.iterNo = pupilPlane.iterNo;
684  return;
685  }
686 
687  for(int i=0; i < m_iTime - 1; ++i)
688  {
689  ++_firstWavefront;
690  if( (size_t) _firstWavefront >= m_wavefronts.size()) _firstWavefront = 0;
691 
692  //std::cerr << m_lastWavefront << " " << m_iTime_counter << " " << _firstWavefront << "\n";
693 
694  pupilPlane.amplitude += m_wavefronts[_firstWavefront].amplitude;
695  pupilPlane.phase += m_wavefronts[_firstWavefront].phase;
696  pupilPlane.iterNo += m_wavefronts[_firstWavefront].iterNo;
697 
698  }
699 
700  ++_firstWavefront;
701  if( (size_t) _firstWavefront >= m_wavefronts.size()) _firstWavefront = 0;
702 
703  //std::cerr << m_lastWavefront << " " << m_iTime_counter << " " << _firstWavefront << "\n";
704 
705  pupilPlane.amplitude += 0.5*m_wavefronts[_firstWavefront].amplitude;
706  pupilPlane.phase += 0.5*m_wavefronts[_firstWavefront].phase;
707  pupilPlane.iterNo += 0.5*m_wavefronts[_firstWavefront].iterNo;
708 
709  pupilPlane.amplitude /= (m_iTime);
710  pupilPlane.phase /= (m_iTime);
711  pupilPlane.iterNo /= (m_iTime);
712 
713  m_wfsImage.image = pupilPlane.phase;
714  m_wfsImage.iterNo = pupilPlane.iterNo;
715 
716 }
717 
718 template<typename _realT, typename _detectorT>
719 void directPhaseSensor<_realT, _detectorT>::applyFilter(bool af)
720 {
721  m_applyFilter = af;
722 }
723 
724 template<typename _realT, typename _detectorT>
725 bool directPhaseSensor<_realT, _detectorT>::applyFilter()
726 {
727  return m_applyFilter;
728 }
729 
730 
731 template<typename _realT, typename _detectorT>
732 void directPhaseSensor<_realT, _detectorT>::filterWidth( int width )
733 {
734  int nr = m_detectorImage.image.rows();
735  int nc = m_detectorImage.image.cols();
736 
737  typename wfsImageT<_realT>::imageT filterMask;
738 
739  filterMask.resize( nr, nc );
740  filterMask.setZero();
741 
742  filterMask.block(0,0, width+1, width+1).setConstant(1.0);
743  filterMask.block(0, nc - width, width+1, width).setConstant(1.0);
744  filterMask.block(nr - width, 0, width, width+1).setConstant(1.0);
745  filterMask.block(nr - width, nc - width, width, width).setConstant(1.0);
746 
747  m_filter.psdSqrt(filterMask,static_cast<realT>(1)/nr,static_cast<realT>(1)/nc);
748 
749  m_filterWidth = width;
750 
751 }
752 
753 template<typename _realT, typename _detectorT>
754 int directPhaseSensor<_realT, _detectorT>::filterWidth()
755 {
756  return m_filterWidth;
757 }
758 
759 template<typename realT, typename detectorT>
760 const sigproc::psdFilter<realT,2> & directPhaseSensor<realT, detectorT>::filter()
761 {
762  return m_filter;
763 }
764 
765 
766 template<typename _realT, typename _detectorT>
767 void directPhaseSensor<_realT, _detectorT>::beta_p(realT bp)
768 {
769  m_beta_p = bp;
770 }
771 
772 template<typename realT, typename detectorT>
773 realT directPhaseSensor<realT, detectorT>::beta_p()
774 {
775  return m_beta_p;
776 }
777 
778 template<typename realT, typename detectorT>
779 void directPhaseSensor<realT, detectorT>::pupil(pupilT * pupil)
780 {
781  m_pupil = pupil;
782 }
783 
784 template<typename realT, typename detectorT>
785 void directPhaseSensor<realT, detectorT>::pupil(pupilT & pupil)
786 {
787  m_pupil = &pupil;
788 }
789 
790 template<typename realT, typename detectorT>
791 typename directPhaseSensor<realT, detectorT>::pupilT * directPhaseSensor<realT, detectorT>::pupil()
792 {
793  return m_pupil;
794 }
795 
796 } //namespace sim
797 
798 } //namespace AO
799 
800 } //namespace mx
801 
802 #endif //directPhaseSensor_hpp
A random number type, which functions like any other arithmetic type.
Definition: randomT.hpp:61
constexpr units::realT c()
The speed of light.
Definition: constants.hpp:60
The mxlib c++ namespace.
Definition: mxError.hpp:107