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