LCOV - code coverage report
Current view: top level - include/ao/sim - directPhaseSensor.hpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 13.6 % 206 28
Test Date: 2026-08-30 22:23:37 Functions: 20.6 % 34 7

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

Generated by: LCOV version 2.0-1