8#ifndef directPhaseSensor_hpp
9#define directPhaseSensor_hpp
19#include "wavefront.hpp"
22#define BREAD_CRUMB std::cout << "DEBUG: " << __FILE__ << " " << __LINE__ << "\n";
34template <
typename _realT>
42 typedef Eigen::Array<realT, Eigen::Dynamic, Eigen::Dynamic> imageT;
47template <
typename _realT,
typename _detectorT>
48class directPhaseSensor
53 typedef std::complex<_realT> complexT;
56 typedef wavefront<_realT> wavefrontT;
62 typedef mx::wfp::imagingArray<std::complex<_realT>, mx::wfp::fftwAllocator<std::complex<_realT>>, 0> complexFieldT;
64 typedef _detectorT detectorT;
66 typedef mx::math::randomT<realT, std::mt19937_64, std::normal_distribution<realT>> norm_distT;
69 typedef mx::math::randomT<long, std::mt19937_64, std::poisson_distribution<long>> poisson_distT;
86 realT m_simStep{ 0.001 };
93 int m_iTime_counter{ 0 };
97 int m_roTime_counter{ 0 };
99 bool m_firstRun{
true };
101 std::vector<wavefrontT> m_wavefronts;
106 wfsImageT<realT> m_wfsImage;
109 bool m_poissonNoise{
true };
116 detectorT m_detector;
119 wfsImageT<realT> m_detectorImage;
137 void detRows(
int sz );
146 void detCols(
int sz );
149 void detSize(
int nrows,
162 void lambda( realT l );
168 void iTime(
int it );
174 void roTime(
int rt );
180 void simStep( realT st );
191 void npix( realT np );
202 void Fbg( realT bg );
204 template <
typename AOSysT>
205 void linkSystem( AOSysT &AOSys );
211 int recordWavefront( wavefrontT &pupilPlane );
217 bool senseWavefront( wavefrontT &pupilPlane );
222 bool senseWavefrontCal( wavefrontT &pupilPlane );
224 void doSenseWavefront();
230 bool m_applyFilter{
false };
235 sigproc::psdFilter<realT, 2> m_filter;
239 void applyFilter(
bool af );
253 void filterWidth(
int width );
265 const sigproc::psdFilter<realT, 2> &filter();
276 norm_distT m_normVar;
277 poisson_distT m_poissonVar;
289 pupilT *m_pupil{
nullptr };
292 typename wfsImageT<realT>::imageT m_noiseIm;
296 void beta_p( realT bp );
307 void pupil( pupilT *pupil );
312 void pupil( pupilT &pupil );
323template <
typename _realT,
typename _detectorT>
324directPhaseSensor<_realT, _detectorT>::directPhaseSensor()
332template <
typename _realT,
typename _detectorT>
333int directPhaseSensor<_realT, _detectorT>::wfSz()
338template <
typename _realT,
typename _detectorT>
339void directPhaseSensor<_realT, _detectorT>::wfSz(
int sz )
347template <
typename _realT,
typename _detectorT>
348int directPhaseSensor<_realT, _detectorT>::detRows()
353template <
typename _realT,
typename _detectorT>
354void directPhaseSensor<_realT, _detectorT>::detRows(
int sz )
356 detSize( sz, m_detCols );
359template <
typename _realT,
typename _detectorT>
360int directPhaseSensor<_realT, _detectorT>::detCols()
365template <
typename _realT,
typename _detectorT>
366void directPhaseSensor<_realT, _detectorT>::detCols(
int sz )
368 detSize( m_detRows, sz );
371template <
typename _realT,
typename _detectorT>
372void directPhaseSensor<_realT, _detectorT>::detSize(
int nrows,
int ncols )
374 if( m_detRows == nrows && m_detCols == ncols )
380 m_detector.setSize( m_detRows, m_detCols );
381 m_detectorImage.image.resize( m_detRows, m_detCols );
384template <
typename _realT,
typename _detectorT>
385_realT directPhaseSensor<_realT, _detectorT>::lambda()
390template <
typename _realT,
typename _detectorT>
391void directPhaseSensor<_realT, _detectorT>::lambda( _realT l )
396template <
typename _realT,
typename _detectorT>
397template <
typename AOSysT>
398void directPhaseSensor<_realT, _detectorT>::linkSystem( AOSysT &AOSys )
400 static_cast<void>( AOSys );
403template <
typename _realT,
typename _detectorT>
404int directPhaseSensor<_realT, _detectorT>::iTime()
409template <
typename _realT,
typename _detectorT>
410void directPhaseSensor<_realT, _detectorT>::iTime(
int it )
414 std::cerr <<
"iTime must be >= 1. Correcting\n";
420 m_wavefronts.resize( m_iTime + 2 + 100 );
421 m_lastWavefront = -1;
423 m_detector.expTime( m_simStep * m_iTime );
426template <
typename _realT,
typename _detectorT>
427int directPhaseSensor<_realT, _detectorT>::roTime()
432template <
typename _realT,
typename _detectorT>
433void directPhaseSensor<_realT, _detectorT>::roTime(
int rt )
437 std::cerr <<
"roTime must be >= 1. Correcting\n";
444template <
typename _realT,
typename _detectorT>
445_realT directPhaseSensor<_realT, _detectorT>::simStep()
450template <
typename _realT,
typename _detectorT>
451void directPhaseSensor<_realT, _detectorT>::simStep( _realT st )
456 m_detector.expTime( m_simStep * m_iTime );
459template <
typename realT,
typename _detectorT>
460realT directPhaseSensor<realT, _detectorT>::npix()
465template <
typename realT,
typename _detectorT>
466void directPhaseSensor<realT, _detectorT>::npix( realT np )
471template <
typename realT,
typename _detectorT>
472realT directPhaseSensor<realT, _detectorT>::Fbg()
477template <
typename realT,
typename _detectorT>
478void directPhaseSensor<realT, _detectorT>::Fbg( realT bg )
483template <
typename _realT,
typename _detectorT>
484int directPhaseSensor<_realT, _detectorT>::recordWavefront( wavefrontT &pupilPlane )
488 if( (
size_t)m_lastWavefront >= m_wavefronts.size() )
491 wavefrontT pPlane = pupilPlane;
493 m_wavefronts[m_lastWavefront].amplitude = pPlane.amplitude;
494 m_wavefronts[m_lastWavefront].phase = pPlane.phase;
495 m_wavefronts[m_lastWavefront].iterNo = pPlane.iterNo;
500template <
typename _realT,
typename _detectorT>
501bool directPhaseSensor<_realT, _detectorT>::senseWavefront( wavefrontT &pupilPlane )
503 using poisson_param_t =
typename std::poisson_distribution<long>::param_type;
506 if( (
size_t)m_lastWavefront >= m_wavefronts.size() )
509 wavefrontT pPlane = pupilPlane;
511 m_wavefronts[m_lastWavefront].amplitude = pPlane.amplitude;
512 m_wavefronts[m_lastWavefront].phase = pPlane.phase;
513 m_wavefronts[m_lastWavefront].iterNo = pPlane.iterNo;
531 if( m_roTime_counter >= m_roTime )
533 m_detectorImage.image = m_wfsImage.image.block(
534 0.5 * ( m_wfsImage.image.rows() - 1 ) - 0.5 * ( m_detectorImage.image.rows() - 1 ),
535 0.5 * ( m_wfsImage.image.cols() - 1 ) - 0.5 * ( m_detectorImage.image.cols() - 1 ),
536 m_detectorImage.image.rows(),
537 m_detectorImage.image.cols() );
539 m_detectorImage.iterNo = m_wfsImage.iterNo;
541 m_roTime_counter = 0;
547 if( m_iTime_counter >= m_iTime )
554 m_roTime_counter = 0;
557 m_detectorImage.image =
558 m_wfsImage.image.block( 0.5 * ( m_wfsImage.image.rows() - 1 ) - 0.5 * ( m_detectorImage.image.rows() - 1 ),
559 0.5 * ( m_wfsImage.image.cols() - 1 ) - 0.5 * ( m_detectorImage.image.cols() - 1 ),
560 m_detectorImage.image.rows(),
561 m_detectorImage.image.cols() );
567 m_filter.filter( m_detectorImage.image );
568 if( m_pupil !=
nullptr )
569 m_detectorImage.image *= *m_pupil;
573 if( m_beta_p > 0 && m_pupil !=
nullptr )
575 m_noiseIm.resize( m_detectorImage.image.rows(), m_detectorImage.image.cols() );
578 for(
int c = 0;
c < m_noiseIm.cols(); ++
c )
580 for(
int r = 0; r < m_noiseIm.rows(); ++r )
583 pow( pupilPlane.amplitude( r, c ), 2 ) * ( *m_pupil )( r,
c ) * m_detector.expTime();
588 realT sqrtFbg = sqrt( m_Fbg * m_detector.expTime() );
591 for(
int c = 0;
c < m_noiseIm.cols(); ++
c )
593 for(
int r = 0; r < m_noiseIm.rows(); ++r )
595 if( m_noiseIm( r, c ) == 0 )
601 realT err = sqrt( m_noiseIm( r, c ) ) * m_normVar;
603 err += sqrtFbg * m_normVar;
604 if( m_detector.ron() > 0 )
605 err += m_detector.ron() * m_normVar;
607 m_detectorImage.image( r, c ) +=
608 m_beta_p * err / m_noiseIm( r, c );
615 m_detectorImage.iterNo = m_wfsImage.iterNo;
617 m_roTime_counter = 0;
627template <
typename _realT,
typename _detectorT>
628bool directPhaseSensor<_realT, _detectorT>::senseWavefrontCal( wavefrontT &pupilPlane )
633 m_wavefronts[0].amplitude = pupilPlane.amplitude;
634 m_wavefronts[0].phase = pupilPlane.phase;
636 m_wavefronts[1].amplitude = pupilPlane.amplitude;
637 m_wavefronts[1].phase = pupilPlane.phase;
641 m_detectorImage.image =
642 m_wfsImage.image.block( 0.5 * ( m_wfsImage.image.rows() - 1 ) - 0.5 * ( m_detectorImage.image.rows() - 1 ),
643 0.5 * ( m_wfsImage.image.cols() - 1 ) - 0.5 * ( m_detectorImage.image.cols() - 1 ),
644 m_detectorImage.image.rows(),
645 m_detectorImage.image.cols() );
649 m_filter.filter( m_detectorImage.image );
655template <
typename _realT,
typename _detectorT>
656void directPhaseSensor<_realT, _detectorT>::doSenseWavefront()
658 wavefrontT pupilPlane;
663 int _firstWavefront = m_lastWavefront - m_iTime;
664 if( _firstWavefront < 0 )
665 _firstWavefront += m_wavefronts.size();
669 pupilPlane.amplitude = 0.5 * m_wavefronts[_firstWavefront].amplitude;
670 pupilPlane.phase = 0.5 * m_wavefronts[_firstWavefront].phase;
672 pupilPlane.iterNo = 0.5 * m_wavefronts[_firstWavefront].iterNo;
677 if( m_wavefronts[_firstWavefront].iterNo < m_iTime )
679 m_wfsImage.image = pupilPlane.phase;
680 m_wfsImage.iterNo = pupilPlane.iterNo;
684 for(
int i = 0; i < m_iTime - 1; ++i )
687 if( (
size_t)_firstWavefront >= m_wavefronts.size() )
692 pupilPlane.amplitude += m_wavefronts[_firstWavefront].amplitude;
693 pupilPlane.phase += m_wavefronts[_firstWavefront].phase;
694 pupilPlane.iterNo += m_wavefronts[_firstWavefront].iterNo;
698 if( (
size_t)_firstWavefront >= m_wavefronts.size() )
703 pupilPlane.amplitude += 0.5 * m_wavefronts[_firstWavefront].amplitude;
704 pupilPlane.phase += 0.5 * m_wavefronts[_firstWavefront].phase;
705 pupilPlane.iterNo += 0.5 * m_wavefronts[_firstWavefront].iterNo;
707 pupilPlane.amplitude /= ( m_iTime );
708 pupilPlane.phase /= ( m_iTime );
709 pupilPlane.iterNo /= ( m_iTime );
711 m_wfsImage.image = pupilPlane.phase;
712 m_wfsImage.iterNo = pupilPlane.iterNo;
715template <
typename _realT,
typename _detectorT>
716void directPhaseSensor<_realT, _detectorT>::applyFilter(
bool af )
721template <
typename _realT,
typename _detectorT>
722bool directPhaseSensor<_realT, _detectorT>::applyFilter()
724 return m_applyFilter;
727template <
typename _realT,
typename _detectorT>
728void directPhaseSensor<_realT, _detectorT>::filterWidth(
int width )
730 int nr = m_detectorImage.image.rows();
731 int nc = m_detectorImage.image.cols();
733 typename wfsImageT<_realT>::imageT filterMask;
735 filterMask.resize( nr, nc );
736 filterMask.setZero();
738 filterMask.block( 0, 0, width + 1, width + 1 ).setConstant( 1.0 );
739 filterMask.block( 0, nc - width, width + 1, width ).setConstant( 1.0 );
740 filterMask.block( nr - width, 0, width, width + 1 ).setConstant( 1.0 );
741 filterMask.block( nr - width, nc - width, width, width ).setConstant( 1.0 );
743 m_filter.psdSqrt( filterMask,
static_cast<realT
>( 1 ) / nr,
static_cast<realT
>( 1 ) / nc );
745 m_filterWidth = width;
748template <
typename _realT,
typename _detectorT>
749int directPhaseSensor<_realT, _detectorT>::filterWidth()
751 return m_filterWidth;
754template <
typename realT,
typename detectorT>
755const sigproc::psdFilter<realT, 2> &directPhaseSensor<realT, detectorT>::filter()
760template <
typename _realT,
typename _detectorT>
761void directPhaseSensor<_realT, _detectorT>::beta_p( realT bp )
766template <
typename realT,
typename detectorT>
767realT directPhaseSensor<realT, detectorT>::beta_p()
772template <
typename realT,
typename detectorT>
773void directPhaseSensor<realT, detectorT>::pupil( pupilT *pupil )
778template <
typename realT,
typename detectorT>
779void directPhaseSensor<realT, detectorT>::pupil( pupilT &pupil )
784template <
typename realT,
typename detectorT>
785typename directPhaseSensor<realT, detectorT>::pupilT *directPhaseSensor<realT, detectorT>::pupil()
An image cube with an Eigen API.
Declares and defines a class to work with a FITS file.
constexpr units::realT c()
The speed of light.
Eigen::Array< scalarT, -1, -1 > eigenImage
Definition of the eigenImage type, which is an alias for Eigen::Array.
Declares and defines a class for filtering with PSDs.
Defines a random number type.