LCOV - code coverage report
Current view: top level - apps/pupilFit - pupilFitter.hpp (source / functions) Coverage Total Hit
Test: MagAOX Lines: 0.0 % 86 0
Test Date: 2026-01-03 21:03:39 Functions: 0.0 % 7 0

            Line data    Source code
       1              : /** \file pupilFitter.hpp
       2              :  * \brief The MagAO-X Pyramid Pupil Fitter class header
       3              :  *
       4              :  * \ingroup pupilFit_files
       5              :  */
       6              : 
       7              : #ifndef pupilFitter_hpp
       8              : #define pupilFitter_hpp
       9              : 
      10              : #include <mx/improc/eigenImage.hpp>
      11              : #include <mx/improc/imageUtils.hpp>
      12              : #include <mx/improc/circleOuterpix.hpp>
      13              : #include <mx/improc/imageTransforms.hpp>
      14              : 
      15              : namespace MagAOX
      16              : {
      17              : namespace app
      18              : {
      19              : 
      20              : /// Struct to perform centration and measure diameter of Pyramid pupils
      21              : template <typename realT>
      22              : struct pupilFitter
      23              : {
      24              :     mx::improc::eigenImage<realT> m_quad;
      25              :     mx::improc::eigenImage<realT> m_quadMag;
      26              :     mx::improc::eigenImage<realT> m_circ;
      27              :     mx::improc::eigenImage<realT> m_circMag;
      28              : 
      29              :     unsigned m_rows{ 0 }; ///< [in] the size of a quad, in rows
      30              :     unsigned m_cols{ 0 }; ///< [in] the size of a quad, in cols
      31              : 
      32              :     int   m_numPupils{ 4 }; ///< the number of pupils.  Default is 4, 3 is also supported.
      33              :     float m_bgMedIndex{ 0.1867 };
      34              :     float m_pupMedIndex{ 0.6867 }; ///< the index of the illuminated pupil median in a sorted array.
      35              : 
      36              :     float m_bg[4]   = { 0, 0, 0, 0 };
      37              :     float m_med[4]  = { 0, 0, 0, 0 };
      38              :     float m_avgx[4] = { 0, 0, 0, 0 };
      39              :     float m_avgy[4] = { 0, 0, 0, 0 };
      40              :     float m_avgr[4] = { 0, 0, 0, 0 };
      41              : 
      42              :     float m_thresh{ 0.5 };
      43              : 
      44              :     std::vector<realT> m_pixs;
      45              : 
      46              :     pupilFitter()
      47              :     {
      48              :     }
      49              : 
      50              :     int setSize( unsigned rows, ///< [in] the new size of a quad, in rows
      51              :                  unsigned cols  ///< [in] the new size of a quad, in cols
      52              :     );
      53              : 
      54              :     /// Returns the quadrant starting coordinates
      55              :     int quadCoords( size_t &i0,    ///< [out] the i coordinate of the lower-left corner of quad
      56              :                     size_t &j0,    ///< [out] the j coordinate of the lower-left corner of auad
      57              :                     int     quadNo ///< [in] the quadrant number
      58              :     );
      59              : 
      60              :     int threshold( mx::improc::eigenImage<realT> &im );
      61              : 
      62              :     int getQuad( mx::improc::eigenImage<realT> &quad, mx::improc::eigenImage<realT> &im, int quadNo );
      63              : 
      64              :     int putQuad( mx::improc::eigenImage<realT> &im, mx::improc::eigenImage<realT> &quad, int quadNo );
      65              : 
      66              :     int outerpix( float &avgx, float &avgy, float &avgr, int quadNo );
      67              : 
      68              :     int fit( mx::improc::eigenImage<realT> &im, mx::improc::eigenImage<realT> &edged );
      69              : 
      70              :     // int emitRegion( const std::string fname );
      71              : };
      72              : 
      73              : template <typename realT>
      74            0 : int pupilFitter<realT>::setSize( unsigned rows, unsigned cols )
      75              : {
      76            0 :     m_rows = rows;
      77            0 :     m_cols = cols;
      78              : 
      79            0 :     m_quad.resize( m_rows, m_cols );
      80            0 :     m_circ.resize( m_rows, m_cols );
      81              : 
      82              :     // Set up for the magnified version
      83            0 :     m_quadMag.resize( m_quad.rows() * 10, m_quad.cols() * 10 );
      84            0 :     m_circMag.resize( m_circ.rows() * 10, m_circ.cols() * 10 );
      85              : 
      86            0 :     m_pixs.resize( m_quadMag.rows() * m_quadMag.cols() );
      87              : 
      88            0 :     return 0;
      89              : }
      90              : 
      91              : template <typename realT>
      92            0 : int pupilFitter<realT>::quadCoords( size_t &i0, size_t &j0, int quadNo )
      93              : {
      94            0 :     if( m_numPupils == 3 )
      95              :     {
      96            0 :         i0 = 0;
      97            0 :         j0 = 0;
      98              : 
      99            0 :         if( quadNo == 1 )
     100              :         {
     101            0 :             i0 = m_rows;
     102              :         }
     103            0 :         if( quadNo == 2 )
     104              :         {
     105            0 :             i0 = 0.5 * m_rows;
     106            0 :             j0 = m_cols;
     107              :         }
     108              :     }
     109              :     else
     110              :     {
     111            0 :         i0 = 0;
     112            0 :         j0 = 0;
     113              : 
     114            0 :         if( quadNo == 1 )
     115            0 :             i0 = m_rows;
     116            0 :         if( quadNo == 2 )
     117            0 :             j0 = m_cols;
     118            0 :         if( quadNo == 3 )
     119              :         {
     120            0 :             i0 = m_rows;
     121            0 :             j0 = m_cols;
     122              :         }
     123              :     }
     124              : 
     125            0 :     return 0;
     126              : }
     127              : 
     128              : template <typename realT>
     129            0 : int pupilFitter<realT>::threshold( mx::improc::eigenImage<realT> &im )
     130              : {
     131            0 :     for( int i = 0; i < im.rows(); ++i )
     132              :     {
     133            0 :         for( int j = 0; j < im.cols(); ++j )
     134              :         {
     135            0 :             if( im( i, j ) >= m_thresh )
     136            0 :                 im( i, j ) = 1;
     137              :             else
     138            0 :                 im( i, j ) = 0;
     139              :         }
     140              :     }
     141              : 
     142            0 :     return 0;
     143              : }
     144              : 
     145              : template <typename realT>
     146            0 : int pupilFitter<realT>::getQuad( mx::improc::eigenImage<realT> &quad, mx::improc::eigenImage<realT> &im, int quadNo )
     147              : {
     148              : 
     149            0 :     if( im.rows() != 2 * m_rows || im.cols() != 2 * m_cols )
     150              :     {
     151            0 :         return -1;
     152              :     }
     153              : 
     154            0 :     size_t i0 = 0, j0 = 0;
     155            0 :     quadCoords( i0, j0, quadNo );
     156              : 
     157            0 :     for( size_t i = i0; i < i0 + m_rows; ++i )
     158              :     {
     159            0 :         for( size_t j = j0; j < j0 + m_cols; ++j )
     160              :         {
     161            0 :             quad( i - i0, j - j0 ) = im( i, j );
     162              :         }
     163              :     }
     164              : 
     165            0 :     return 0;
     166              : }
     167              : 
     168              : template <typename realT>
     169            0 : int pupilFitter<realT>::putQuad( mx::improc::eigenImage<realT> &im, mx::improc::eigenImage<realT> &quad, int quadNo )
     170              : {
     171            0 :     if( im.rows() != 2 * m_rows || im.cols() != 2 * m_cols )
     172              :     {
     173            0 :         return -1;
     174              :     }
     175              : 
     176            0 :     size_t i0 = 0, j0 = 0;
     177            0 :     quadCoords( i0, j0, quadNo );
     178              : 
     179            0 :     for( size_t i = i0; i < i0 + m_rows; ++i )
     180              :     {
     181            0 :         for( size_t j = j0; j < j0 + m_cols; ++j )
     182              :         {
     183            0 :             im( i, j ) = quad( i - i0, j - j0 );
     184              :             ;
     185              :         }
     186              :     }
     187              : 
     188            0 :     return 0;
     189              : }
     190              : 
     191              : template <typename realT>
     192            0 : int pupilFitter<realT>::outerpix( float &avgx, float &avgy, float &avgr, int quadNo )
     193              : {
     194              : 
     195              :     realT x0, y0, avgr0;
     196              : 
     197            0 :     mx::improc::circleOuterpix( x0, y0, avgr0, avgx, avgy, avgr, m_circMag, m_quadMag );
     198              : 
     199            0 :     avgx /= 10.0;
     200            0 :     avgy /= 10.0;
     201            0 :     avgr /= 10.0;
     202              : 
     203            0 :     size_t i0 = 0, j0 = 0;
     204            0 :     quadCoords( i0, j0, quadNo );
     205              : 
     206            0 :     avgx += i0;
     207            0 :     avgy += j0;
     208              : 
     209            0 :     return 0;
     210              : }
     211              : 
     212              : template <typename realT>
     213            0 : int pupilFitter<realT>::fit( mx::improc::eigenImage<realT> &im, mx::improc::eigenImage<realT> &edged )
     214              : {
     215              :     try
     216              :     {
     217              : 
     218            0 :         mx::improc::eigenImage<realT> imin = im;
     219            0 :         im.setZero();
     220            0 :         for( int i = 0; i < m_numPupils; ++i )
     221              :         {
     222              :             // 0) magnify the image
     223            0 :             getQuad( m_quad, imin, i );
     224              : 
     225            0 :             mx::improc::imageMagnify( m_quadMag, m_quad, mx::improc::bilinearTransform<realT>() );
     226              : 
     227              :             // 1) normalize by median of pupil
     228              : 
     229            0 :             for( size_t j = 0; j < m_pixs.size(); ++j )
     230              :             {
     231            0 :                 m_pixs[j] = m_quadMag.data()[j];
     232              :             }
     233              : 
     234            0 :             std::sort( m_pixs.begin(), m_pixs.end() );
     235              : 
     236            0 :             m_bg[i] = m_pixs[m_bgMedIndex * m_pixs.size()];
     237              : 
     238            0 :             m_med[i] = m_pixs[m_pupMedIndex * m_pixs.size()]; // This should be the median of the pupils if the right
     239              :                                                               // size and contained in the quad
     240              : 
     241            0 :             m_quadMag = ( m_quadMag - m_bg[i] ) / ( m_med[i] - m_bg[i] );
     242              : 
     243              :             // 2) Threshold the normalized quad
     244            0 :             threshold( m_quadMag );
     245              : 
     246              :             // 3) Find outer pixels and the radius
     247            0 :             outerpix( m_avgx[i], m_avgy[i], m_avgr[i], i );
     248              : 
     249              :             // 4) De-magnify and prepare for putting on the streams
     250            0 :             mx::improc::imageRebinSum( m_quad, m_quadMag, true );
     251            0 :             mx::improc::imageRebinSum( m_circ, m_circMag );
     252            0 :             putQuad( im, m_quad, i );
     253            0 :             putQuad( edged, m_circ, i );
     254              :         }
     255              : 
     256            0 :         return 0;
     257            0 :     }
     258            0 :     catch( const std::exception &e )
     259              :     {
     260            0 :         std::cerr << __FILE__ << ' ' << __LINE__ << ' ' << e.what() << '\n';
     261            0 :         return -1;
     262              :     }
     263              : }
     264              : } // namespace app
     265              : } // namespace MagAOX
     266              : 
     267              : #endif // pupilFitter_hpp
        

Generated by: LCOV version 2.0-1