LCOV - code coverage report
Current view: top level - include/ao/analysis - aoWFS.hpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 26.7 % 86 23
Test Date: 2026-08-30 22:23:37 Functions: 33.3 % 18 6

            Line data    Source code
       1              : /** \file aoWFS.hpp
       2              :  * \author Jared R. Males (jaredmales@gmail.com)
       3              :  * \brief Definitions of various analytic wavefront sensors
       4              :  * \ingroup mxAO_files
       5              :  *
       6              :  */
       7              : 
       8              : #ifndef aoWFS_hpp
       9              : #define aoWFS_hpp
      10              : 
      11              : #include "../../math/constants.hpp"
      12              : #include "../../mxlib.hpp"
      13              : #include "../../improc/eigenImage.hpp"
      14              : #include "../../ioutils/fits/fitsFile.hpp"
      15              : 
      16              : namespace mx
      17              : {
      18              : namespace AO
      19              : {
      20              : namespace analysis
      21              : {
      22              : 
      23              : /// The ideal wavefront sensor sensitivity function.
      24              : /** Provides the \f$ \beta_p \f$ parameter of Guyon, 2005 \cite guyon_2005
      25              :  * for the ideal WFS.
      26              :  *
      27              :  * This is the base class for all WFS.
      28              :  *
      29              :  * \tparam realT is the floating point type used for calculations
      30              :  * \tparam iosT is an output stream type with operator \<\< defined (default is std::ostream)
      31              :  *
      32              :  * \ingroup mxAOAnalytic
      33              :  */
      34              : template <typename realT, typename iosT = std::ostream>
      35              : struct wfs
      36              : {
      37              :     std::string _id;
      38              : 
      39              :     /// Constructor
      40              :     /** Only sets the value of _id.
      41              :      */
      42           52 :     wfs()
      43           52 :     {
      44           52 :         _id = "Ideal WFS";
      45           52 :     }
      46              : 
      47              :     /// Destructor
      48              :     /** Declared virtual so more complicated derived types can be created.
      49              :      */
      50          101 :     virtual ~wfs()
      51              :     {
      52          104 :         return;
      53          101 :     }
      54              : 
      55              :     /// Get the photon noise sensitivity at a spatial frequency.
      56              :     /** The sensitivity of the ideal WFS is 1 at all k \cite guyon_2005.
      57              :      *
      58              :      * \returns the sensitivity to photon noise parameter
      59              :      */
      60            0 :     virtual realT beta_p( int m,   ///< [in] the spatial frequency index for u (not used by this WFS)
      61              :                           int n,   ///< [in] the spatial frequency index for v (not used by this WFS)
      62              :                           realT D, ///< [in] the telescope diameter (not used by this WFS)
      63              :                           realT d, ///< [in] the sub-ap spacing (not used by this WFS)
      64              :                           realT r0 ///< [in] Fried's parameter (not used by this WFS)
      65              :     )
      66              :     {
      67              :         // Stuff a sock in the compiler's mouth:
      68              :         static_cast<void>( m );
      69              :         static_cast<void>( n );
      70              :         static_cast<void>( D );
      71              :         static_cast<void>( d );
      72              :         static_cast<void>( r0 );
      73              : 
      74            0 :         return static_cast<realT>( 1 );
      75              :     }
      76              : 
      77              :     /// Get the read noise sensitivity at a spatial frequency.
      78              :     /** Here we assume beta_r is the same as beta_p.
      79              :      *
      80              :      * \returns the sensitivity to read noise parameter
      81              :      */
      82            0 :     virtual realT beta_r( int m,   ///< [in] the spatial frequency index for u (not used by this WFS)
      83              :                           int n,   ///< [in] the spatial frequency index for v (not used by this WFS)
      84              :                           realT D, ///< [in] the telescope diameter (not used by this WFS)
      85              :                           realT d, ///< [in] the sub-ap spacing (not used by this WFS)
      86              :                           realT r0 ///< [in] Fried's parameter (not used by this WFS)
      87              :     )
      88              :     {
      89            0 :         return beta_p( m, n, D, d, r0 );
      90              :     }
      91              : 
      92              :     /// Dump the details of the WFS to an io stream.
      93              :     /** Is virtual so that derived types can add parameters.
      94              :      */
      95            1 :     virtual iosT &dumpWFS( iosT &ios )
      96              :     {
      97            1 :         ios << "# WFS Parameters:\n";
      98            1 :         ios << "#    ID = " << _id << '\n';
      99              : 
     100            1 :         return ios;
     101              :     }
     102              : };
     103              : 
     104              : /// The unmodulated pyramid wavefront sensor sensitivity function.
     105              : /** Provides the \f$ \beta_p \f$ parameter of Guyon, 2005 \cite guyon_2005
     106              :  * for the unmodulated PyWFS.
     107              :  *
     108              :  * \tparam realT is the floating point type used for calculations
     109              :  * \tparam iosT is an output stream type with operator \<\< defined (default is std::ostream)
     110              :  *
     111              :  * \ingroup mxAOAnalytic
     112              :  */
     113              : template <typename realT, typename iosT = std::ostream>
     114              : struct pywfsUnmod : public wfs<realT, iosT>
     115              : {
     116            1 :     pywfsUnmod()
     117            1 :     {
     118            1 :         this->_id = "Unmodulated Pyramid";
     119            1 :     }
     120              : 
     121              :     /// Get the photon noise sensitivity at a spatial frequency.
     122              :     /** The sensitivity of the unmodulated PyWFS is \f$ \sqrt{2} \f$ at all k.
     123              :      *
     124              :      * \returns the sensitivity to photon noise parameter
     125              :      */
     126            0 :     virtual realT beta_p( int m,   ///< [in] the spatial frequency index for u (not used by this WFS)
     127              :                           int n,   ///< [in] the spatial frequency index for v (not used by this WFS)
     128              :                           realT D, ///< [in] the telescope diameter (not used by this WFS)
     129              :                           realT d, ///< [in] the sub-ap spacing (not used by this WFS)
     130              :                           realT r0 ///< [in] Fried's parameter (not used by this WFS)
     131              :     )
     132              :     {
     133              :         // Stuff a sock in the compiler's mouth:
     134              :         static_cast<void>( m );
     135              :         static_cast<void>( n );
     136              :         static_cast<void>( D );
     137              :         static_cast<void>( d );
     138              :         static_cast<void>( r0 );
     139              : 
     140            0 :         return math::root_two<realT>();
     141              :     }
     142              : 
     143              :     /// Get the read noise sensitivity at a spatial frequency.
     144              :     /** Here we assume that beta_r is the same as beta_p.
     145              :      *
     146              :      * \returns the sensitivity to read noise parameter
     147              :      */
     148            0 :     virtual realT beta_r( int m,   ///< [in] the spatial frequency index for u (not used by this WFS)
     149              :                           int n,   ///< [in] the spatial frequency index for v (not used by this WFS)
     150              :                           realT D, ///< [in] the telescope diameter (not used by this WFS)
     151              :                           realT d, ///< [in] the sub-ap spacing (not used by this WFS)
     152              :                           realT r0 ///< [in] Fried's parameter (not used by this WFS)
     153              :     )
     154              :     {
     155            0 :         return beta_p( m, n, D, d, r0 );
     156              :     }
     157              : };
     158              : 
     159              : /// The asymptotic modulated pyramid wavefront sensor sensitivity function.
     160              : /** Provides the \f$ \beta_p \f$ parameter of Guyon, 2005 \cite guyon_2005
     161              :  * for the modulated PyWFS in the asymptotic limit.
     162              :  *
     163              :  * \tparam realT is the floating point type used for calculations
     164              :  * \tparam iosT is an output stream type with operator \<\< defined (default is std::ostream)
     165              :  *
     166              :  * \ingroup mxAOAnalytic
     167              :  */
     168              : template <typename realT, typename iosT = std::ostream>
     169              : struct pywfsModAsymptotic : public wfs<realT, iosT>
     170              : {
     171            1 :     pywfsModAsymptotic()
     172            1 :     {
     173            1 :         this->_id = "Asymptotic Modulated Pyramid";
     174            1 :     }
     175              : 
     176              :     /// Get the photon sensitivity at a spatial frequency.
     177              :     /** The photon noise sensitivity of the asymptotic modulated PyWFS is \f$ 2 \sqrt{2} \f$ at all k.
     178              :      *
     179              :      * \returns the sensitivity to photon noise parameter
     180              :      */
     181            0 :     virtual realT beta_p( int m,   ///< [in] the spatial frequency index for u (not used by this WFS)
     182              :                           int n,   ///< [in] the spatial frequency index for v (not used by this WFS)
     183              :                           realT D, ///< [in] the telescope diameter (not used by this WFS)
     184              :                           realT d, ///< [in] the sub-ap spacing (not used by this WFS)
     185              :                           realT r0 ///< [in] Fried's parameter (not used by this WFS)
     186              :     )
     187              :     {
     188              :         // Stuff a sock in the compiler's mouth:
     189              :         static_cast<void>( m );
     190              :         static_cast<void>( n );
     191              :         static_cast<void>( D );
     192              :         static_cast<void>( d );
     193              :         static_cast<void>( r0 );
     194              : 
     195            0 :         return static_cast<realT>( 2 ) * math::root_two<realT>();
     196              :     }
     197              : 
     198              :     /// Get the read noise sensitivity at a spatial frequency.
     199              :     /** Here we assume beta_r is the same as beta_p
     200              :      *
     201              :      * \returns the sensitivity to read noise parameter
     202              :      */
     203            0 :     virtual realT beta_r( int m,   ///< [in] the spatial frequency index for u (not used by this WFS)
     204              :                           int n,   ///< [in] the spatial frequency index for v (not used by this WFS)
     205              :                           realT D, ///< [in] the telescope diameter (not used by this WFS)
     206              :                           realT d, ///< [in] the sub-ap spacing (not used by this WFS)
     207              :                           realT r0 ///< [in] Fried's parameter (not used by this WFS)
     208              :     )
     209              :     {
     210            0 :         return beta_p( m, m, D, d, r0 );
     211              :     }
     212              : };
     213              : 
     214              : /// The shack hartmann wavefront sensor sensitivity function.
     215              : /** Provides the \f$ \beta_p \f$ parameter of Guyon, 2005 \cite guyon_2005
     216              :  * for the shack hartmann WFS.
     217              :  *
     218              :  * \tparam realT is the floating point type used for calculations
     219              :  * \tparam iosT is an output stream type with operator \<\< defined (default is std::ostream)
     220              :  *
     221              :  * \ingroup mxAOAnalytic
     222              :  */
     223              : template <typename realT, typename iosT = std::ostream>
     224              : struct shwfs : public wfs<realT, iosT>
     225              : {
     226            1 :     shwfs()
     227            1 :     {
     228            1 :         this->_id = "Shack Hartmann";
     229            1 :     }
     230              : 
     231              :     /// Get the photon noise sensitivity at a spatial frequency.
     232              :     /** The photon noise sensitivity of the shack hartmann WFS
     233              :      *
     234              :      * \returns the sensitivity to photon noise parameter
     235              :      */
     236            0 :     virtual realT beta_p( int m,   ///< [in] the spatial frequency index for u
     237              :                           int n,   ///< [in] the spatial frequency index for v
     238              :                           realT D, ///< [in] the telescope diameter
     239              :                           realT d, ///< [in] the sub-ap spacing
     240              :                           realT r0 ///< [in] Fried's parameter
     241              :     )
     242              :     {
     243            0 :         realT k = sqrt( m * m + n * n ) / D;
     244              : 
     245            0 :         return 1.48 / ( k * d ) * sqrt( 1 + pow( d / r0, 2 ) );
     246              :     }
     247              : 
     248              :     /// Get the read noise sensitivity at a spatial frequency.
     249              :     /** Here we assume beta_r = beta_p
     250              :      *
     251              :      * \returns the sensitivity to read noise parameter
     252              :      */
     253            0 :     virtual realT beta_r( int m,   ///< [in] the spatial frequency index for u
     254              :                           int n,   ///< [in] the spatial frequency index for v
     255              :                           realT D, ///< [in] the telescope diameter
     256              :                           realT d, ///< [in] the sub-ap spacing
     257              :                           realT r0 ///< [in] Fried's parameter
     258              :     )
     259              :     {
     260            0 :         return beta_p( m, n, D, d, r0 );
     261              :     }
     262              : };
     263              : 
     264              : /// The calculated WFS uses sensitivities provided by FITS files
     265              : /** Provides the \f$ \beta_p \f$ and \f$ \beta_r \f$ parameters
     266              :  * from FITS files.
     267              :  *
     268              :  * \tparam realT is the floating point type used for calculations
     269              :  * \tparam iosT is an output stream type with operator \<\< defined (default is std::ostream)
     270              :  *
     271              :  * \ingroup mxAOAnalytic
     272              :  */
     273              : template <typename realT, typename iosT = std::ostream>
     274              : struct calculatedWFS : public wfs<realT, iosT>
     275              : {
     276              :     typedef verbose::d verboseT;
     277              : 
     278              :     std::string m_beta_p_file;
     279              :     std::string m_beta_r_file;
     280              :     bool m_sensitivity{ false };
     281              : 
     282              :     improc::eigenImage<realT> m_beta_p;
     283              :     improc::eigenImage<realT> m_beta_r;
     284              : 
     285            0 :     calculatedWFS()
     286            0 :     {
     287            0 :         this->_id = "Calculated WFS";
     288            0 :     }
     289              : 
     290              :     /// Get the photon noise sensitivity at a spatial frequency.
     291              :     /** The photon noise sensitivity from the FITS file is returned.
     292              :      *
     293              :      * \returns the sensitivity to photon noise parameter
     294              :      */
     295            0 :     virtual realT beta_p( int m,   ///< [in] the spatial frequency index for u
     296              :                           int n,   ///< [in] the spatial frequency index for v
     297              :                           realT D, ///< [in] the telescope diameter
     298              :                           realT d, ///< [in] the sub-ap spacing
     299              :                           realT r0 ///< [in] Fried's parameter
     300              :     )
     301              :     {
     302              : 
     303            0 :         if( m_beta_p.rows() == 0 )
     304              :         {
     305            0 : #pragma omp critical // Make sure we don't race in m/t
     306              :             {
     307            0 :                 if( m_beta_p.rows() == 0 ) // Check again after critical locks
     308              :                 {
     309            0 :                     fits::fitsFile<realT> ff;
     310            0 :                     ff.read( m_beta_p, m_beta_p_file );
     311              : 
     312            0 :                     if( m_sensitivity )
     313              :                     {
     314            0 :                         m_beta_p = 1.0 / m_beta_p;
     315              :                     }
     316            0 :                 }
     317              :             }
     318              :         }
     319              : 
     320            0 :         int midx = 0.5 * ( m_beta_p.rows() - 1.0 ) + m;
     321            0 :         int nidx = 0.5 * ( m_beta_p.cols() - 1.0 ) + n;
     322              : 
     323            0 :         if( midx > m_beta_p.rows() - 1 || midx < 0 )
     324              :         {
     325            0 : #pragma omp critical
     326              :             {
     327            0 :                 std::cerr << "calculatedWFS::beta_p: m index out of range. Got m = " << m
     328            0 :                           << "  / beta_p.rows = " << m_beta_p.rows() << "\n";
     329              :             }
     330              :             // Just return a huge number to make this spatial frequency unsenseable
     331            0 :             return std::numeric_limits<realT>::max();
     332              :         }
     333              : 
     334            0 :         if( nidx > m_beta_p.cols() - 1 || nidx < 0 )
     335              :         {
     336            0 : #pragma omp critical
     337              :             {
     338            0 :                 std::cerr << "calculatedWFS::beta_p: n index out of range. Got n = " << n
     339            0 :                           << "  / beta_p.cols = " << m_beta_p.cols() << "\n";
     340              :             }
     341              :             // Just return a huge number to make this spatial frequency unsenseable
     342            0 :             return std::numeric_limits<realT>::max();
     343              :         }
     344              : 
     345            0 :         return m_beta_p( midx, nidx );
     346              :     }
     347              : 
     348              :     /// Get the read noise sensitivity at a spatial frequency.
     349              :     /** The read noise sensitivity from the FITS file is returned.
     350              :      *
     351              :      * \returns the sensitivity to read noise parameter
     352              :      */
     353            0 :     virtual realT beta_r( int m,   ///< [in] the spatial frequency index for u
     354              :                           int n,   ///< [in] the spatial frequency index for v
     355              :                           realT D, ///< [in] the telescope diameter
     356              :                           realT d, ///< [in] the sub-ap spacing
     357              :                           realT r0 ///< [in] Fried's parameter
     358              :     )
     359              :     {
     360            0 :         if( m_beta_r.rows() == 0 )
     361              :         {
     362            0 :             fits::fitsFile<realT> ff;
     363            0 :             ff.read( m_beta_r, m_beta_r_file );
     364              : 
     365            0 :             if( m_sensitivity )
     366            0 :                 m_beta_r = 1.0 / m_beta_r;
     367            0 :         }
     368              : 
     369            0 :         int midx = 0.5 * ( m_beta_r.rows() - 1.0 ) + m;
     370            0 :         int nidx = 0.5 * ( m_beta_r.cols() - 1.0 ) + n;
     371              : 
     372            0 :         if( midx > m_beta_r.rows() - 1 || midx < 0 )
     373              :         {
     374            0 :             throw(mx::exception<verboseT>(error_t::sizeerr, "m index out of range" ));
     375              :         }
     376              : 
     377            0 :         if( nidx > m_beta_r.cols() - 1 || nidx < 0 )
     378              :         {
     379            0 :             throw(mx::exception<verboseT>(error_t::sizeerr, "n index out of range" ));
     380              :         }
     381              : 
     382            0 :         return m_beta_r( midx, nidx );
     383              :     }
     384              : 
     385              :     /// Dump the details of the WFS to an io stream.
     386              :     /** Is virtual so that derived types can add parameters.
     387              :      */
     388            0 :     virtual iosT &dumpWFS( iosT &ios )
     389              :     {
     390            0 :         wfs<realT, iosT>::dumpWFS( ios );
     391              : 
     392            0 :         ios << "#    beta_p = " << m_beta_p_file << '\n';
     393            0 :         ios << "#    beta_r = " << m_beta_r_file << '\n';
     394            0 :         ios << "#    sensitivity = " << std::boolalpha << m_sensitivity << "\n";
     395              : 
     396            0 :         return ios;
     397              :     }
     398              : };
     399              : 
     400              : } // namespace analysis
     401              : } // namespace AO
     402              : } // namespace mx
     403              : 
     404              : #endif // aoWFS_hpp
        

Generated by: LCOV version 2.0-1