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

            Line data    Source code
       1              : /** \file strehlEstimator.hpp
       2              :  * \brief The MagAO-X XXXXXX header file
       3              :  *
       4              :  * \ingroup strehlEstimator_files
       5              :  */
       6              : 
       7              : #ifndef strehlEstimator_hpp
       8              : #define strehlEstimator_hpp
       9              : 
      10              : #include <mx/ao/analysis/aoSystem.hpp>
      11              : using namespace mx::math;
      12              : 
      13              : #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
      14              : #include "../../magaox_git_version.h"
      15              : 
      16              : /** \defgroup strehlEstimator
      17              :  * \brief The XXXXXX application to do YYYYYYY
      18              :  *
      19              :  * <a href="../handbook/operating/software/apps/XXXXXX.html">Application Documentation</a>
      20              :  *
      21              :  * \ingroup apps
      22              :  *
      23              :  */
      24              : 
      25              : /** \defgroup strehlEstimator_files
      26              :  * \ingroup strehlEstimator
      27              :  */
      28              : 
      29              : namespace MagAOX
      30              : {
      31              : namespace app
      32              : {
      33              : 
      34              : struct wfsavgShmimT
      35              : {
      36            0 :     static std::string configSection()
      37              :     {
      38            0 :         return "wfsavgShmim";
      39              :     };
      40              : 
      41            0 :     static std::string indiPrefix()
      42              :     {
      43            0 :         return "wfsavg";
      44              :     };
      45              : };
      46              : 
      47              : struct wfsmaskShmimT
      48              : {
      49            0 :     static std::string configSection()
      50              :     {
      51            0 :         return "wfsmaskShmim";
      52              :     };
      53              : 
      54            0 :     static std::string indiPrefix()
      55              :     {
      56            0 :         return "wfsmask";
      57              :     };
      58              : };
      59              : 
      60              : /// The MagAO-X xxxxxxxx
      61              : /**
      62              :  * \ingroup strehlEstimator
      63              :  */
      64              : class strehlEstimator : public MagAOXApp<true>,
      65              :                         dev::shmimMonitor<strehlEstimator, wfsavgShmimT>,
      66              :                         dev::shmimMonitor<strehlEstimator, wfsmaskShmimT>
      67              : {
      68              : 
      69              :     // Give the test harness access.
      70              :     friend class strehlEstimator_test;
      71              : 
      72              :     friend class dev::shmimMonitor<strehlEstimator, wfsavgShmimT>;
      73              :     friend class dev::shmimMonitor<strehlEstimator, wfsmaskShmimT>;
      74              : 
      75              :   public:
      76              :     typedef dev::shmimMonitor<strehlEstimator, wfsavgShmimT>  wfsavgShmimMonitorT;
      77              :     typedef dev::shmimMonitor<strehlEstimator, wfsmaskShmimT> wfsmaskShmimMonitorT;
      78              : 
      79              :   protected:
      80              :     /** \name Configurable Parameters
      81              :      *@{
      82              :      */
      83              : 
      84              :     int m_loopNum{ 1 }; ///< The number of the loop. Used to set shmim names, as in aolN_wfsmask.
      85              : 
      86              :     std::string m_wfsDevice{ "camwfs" };
      87              : 
      88              :     std::string m_stagebsDevice{ "stagebs" };
      89              : 
      90              :     float m_again{ 28.547 };
      91              : 
      92              :     float m_qe{ 0.53 };
      93              : 
      94              :     float m_F0_6535{ 4.2e10 };
      95              : 
      96              :     float m_F0_HaIR{ 5.3e10 };
      97              : 
      98              :     float m_lam0_6535{ 0.791 };
      99              : 
     100              :     float m_lam0_HaIR{ 0.837 };
     101              : 
     102              :     float m_qe_6535{ 0.53 };
     103              : 
     104              :     float m_qe_HaIR{ 0.53 };
     105              : 
     106              :     ///@}
     107              : 
     108              :     float m_fps{ 2000 };
     109              : 
     110              :     float m_emg{ 1 };
     111              : 
     112              :     float m_F0{ m_F0_6535 };
     113              : 
     114              :     float m_lam0{ m_lam0_6535 };
     115              : 
     116              :     float m_seeing{ 0.64 };
     117              : 
     118              :     float m_r0{ 0.16 };
     119              : 
     120              :     float m_elevation{ 90 };
     121              : 
     122              :     int m_npix;
     123              : 
     124              :     float m_counts{ 0 };
     125              : 
     126              :     float m_mag{ 0 };
     127              : 
     128              :     mx::improc::eigenImage<float> m_wfsmask;
     129              :     mx::improc::eigenImage<float> m_wfsavg;
     130              : 
     131              :     mx::AO::analysis::aoSystem<float, mx::AO::analysis::vonKarmanSpectrum<float>> m_aosys;
     132              : 
     133              :     double m_dimm_fwhm_corr{ 0 }; ///< DIMM elevation corrected FWHM
     134              :     int    m_dimm_time{ 0 };      ///< Seconds since midnight of DIMM measurement.
     135              : 
     136              :     double m_mag1_fwhm_corr{ 0 }; ///< MAG1 elevation corrected FWHM
     137              :     int    m_mag1_time{ 0 };      ///< Seconds since midnight of MAG1 measurement.
     138              : 
     139              :     double m_mag2_fwhm_corr{ 0 }; ///< MAG2 elevation corrected FWHM
     140              :     int    m_mag2_time{ 0 };      ///< Seconds since midnight of MAG2 measurement.
     141              : 
     142              :   public:
     143              :     /// Default c'tor.
     144              :     strehlEstimator();
     145              : 
     146              :     /// D'tor, declared and defined for noexcept.
     147            0 :     ~strehlEstimator() noexcept
     148            0 :     {
     149            0 :     }
     150              : 
     151              :     virtual void setupConfig();
     152              : 
     153              :     /// Implementation of loadConfig logic, separated for testing.
     154              :     /** This is called by loadConfig().
     155              :      */
     156              :     int loadConfigImpl(
     157              :         mx::app::appConfigurator &_config /**< [in] an application configuration from which to load values*/ );
     158              : 
     159              :     virtual void loadConfig();
     160              : 
     161              :     /// Startup function
     162              :     /**
     163              :      *
     164              :      */
     165              :     virtual int appStartup();
     166              : 
     167              :     /// Implementation of the FSM for strehlEstimator.
     168              :     /**
     169              :      * \returns 0 on no critical error
     170              :      * \returns -1 on an error requiring shutdown
     171              :      */
     172              :     virtual int appLogic();
     173              : 
     174              :     /// Shutdown the app.
     175              :     /**
     176              :      *
     177              :      */
     178              :     virtual int appShutdown();
     179              : 
     180              :     int allocate( const wfsavgShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     181              :     );
     182              : 
     183              :     int processImage( void *curr_src,      ///< [in] pointer to the start of the current frame
     184              :                       const wfsavgShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     185              :     );
     186              : 
     187              :     int allocate( const wfsmaskShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     188              :     );
     189              : 
     190              :     int processImage( void *curr_src,       ///< [in] pointer to the start of the current frame
     191              :                       const wfsmaskShmimT & ///< [in] tag to differentiate shmimMonitor parents.
     192              :     );
     193              : 
     194              :     void calcMag();
     195              : 
     196              :     /** INDI
     197              :      * @{
     198              :      */
     199              : 
     200              :     pcf::IndiProperty m_indiP_fps;
     201              :     pcf::IndiProperty m_indiP_emg;
     202              : 
     203              :     pcf::IndiProperty m_indiP_stage;
     204              : 
     205              :     pcf::IndiProperty m_indiP_tcsi_seeing;
     206              :     pcf::IndiProperty m_indiP_tcsi_telpos;
     207              :     pcf::IndiProperty m_indiP_seeing_magaox;
     208              : 
     209              :     pcf::IndiProperty m_indiP_mag;
     210              :     pcf::IndiProperty m_indiP_strehl;
     211              :     pcf::IndiProperty m_indiP_wfe;
     212              : 
     213            0 :     INDI_SETCALLBACK_DECL( strehlEstimator, m_indiP_fps );
     214            0 :     INDI_SETCALLBACK_DECL( strehlEstimator, m_indiP_emg );
     215            0 :     INDI_SETCALLBACK_DECL( strehlEstimator, m_indiP_stage );
     216            0 :     INDI_SETCALLBACK_DECL( strehlEstimator, m_indiP_tcsi_seeing );
     217            0 :     INDI_SETCALLBACK_DECL( strehlEstimator, m_indiP_tcsi_telpos );
     218              : 
     219              :     ///@}
     220              : };
     221              : 
     222            0 : strehlEstimator::strehlEstimator() : MagAOXApp( MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED )
     223              : {
     224              : 
     225            0 :     wfsavgShmimMonitorT::m_getExistingFirst  = true;
     226            0 :     wfsmaskShmimMonitorT::m_getExistingFirst = true;
     227              : 
     228            0 :     return;
     229            0 : }
     230              : 
     231            0 : void strehlEstimator::setupConfig()
     232              : {
     233            0 :     m_aosys.loadMagAOX();
     234              : 
     235            0 :     config.add( "loop.number",
     236              :                 "",
     237              :                 "loop.number",
     238              :                 argType::Required,
     239              :                 "loop",
     240              :                 "number",
     241              :                 false,
     242              :                 "int",
     243              :                 "The number of the loop. Used to set shmim names, as in aolN_mgainfact." );
     244              : 
     245            0 :     config.add( "phot.qe_6535",
     246              :                 "",
     247              :                 "phot.qe_6535",
     248              :                 argType::Required,
     249              :                 "phot",
     250              :                 "qe_6535",
     251              :                 false,
     252              :                 "float",
     253              :                 "The WFS QE in the 65-35 B/S." );
     254              : 
     255            0 :     config.add( "phot.qe_HaIR",
     256              :                 "",
     257              :                 "phot.qe_HaIR",
     258              :                 argType::Required,
     259              :                 "phot",
     260              :                 "qe_HaIR",
     261              :                 false,
     262              :                 "float",
     263              :                 "The WFS QE in the Ha-IR B/S." );
     264              : 
     265            0 :     SHMIMMONITORT_SETUP_CONFIG( wfsavgShmimMonitorT, config );
     266            0 :     SHMIMMONITORT_SETUP_CONFIG( wfsmaskShmimMonitorT, config );
     267              : }
     268              : 
     269            0 : int strehlEstimator::loadConfigImpl( mx::app::appConfigurator &_config )
     270              : {
     271              : 
     272            0 :     _config( m_loopNum, "loop.number" );
     273              : 
     274            0 :     _config( m_qe_6535, "phot.qe_6535" );
     275            0 :     _config( m_qe_HaIR, "phot.qe_HaIR" );
     276              : 
     277              :     char shmim[1024];
     278            0 :     snprintf( shmim, sizeof( shmim ), "aol%d_wfsavg", m_loopNum );
     279            0 :     wfsavgShmimMonitorT::m_shmimName = shmim;
     280            0 :     SHMIMMONITORT_LOAD_CONFIG( wfsavgShmimMonitorT, _config );
     281              : 
     282            0 :     snprintf( shmim, sizeof( shmim ), "aol%d_wfsmask", m_loopNum );
     283            0 :     wfsmaskShmimMonitorT::m_shmimName = shmim;
     284            0 :     SHMIMMONITORT_LOAD_CONFIG( wfsmaskShmimMonitorT, _config );
     285              : 
     286            0 :     return 0;
     287              : }
     288              : 
     289            0 : void strehlEstimator::loadConfig()
     290              : {
     291            0 :     loadConfigImpl( config );
     292            0 : }
     293              : 
     294            0 : int strehlEstimator::appStartup()
     295              : {
     296              : 
     297            0 :     SHMIMMONITORT_APP_STARTUP( wfsavgShmimMonitorT );
     298            0 :     SHMIMMONITORT_APP_STARTUP( wfsmaskShmimMonitorT );
     299              : 
     300            0 :     REG_INDI_SETPROP( m_indiP_fps, m_wfsDevice, "fps" );
     301              : 
     302            0 :     REG_INDI_SETPROP( m_indiP_emg, m_wfsDevice, "emgain" );
     303              : 
     304            0 :     REG_INDI_SETPROP( m_indiP_stage, m_stagebsDevice, "presetName" );
     305              : 
     306            0 :     REG_INDI_SETPROP( m_indiP_tcsi_seeing, "tcsi", "seeing" );
     307            0 :     REG_INDI_SETPROP( m_indiP_tcsi_telpos, "tcsi", "telpos" );
     308              : 
     309            0 :     CREATE_REG_INDI_RO_NUMBER( m_indiP_mag, "star_mag", "Star Magnitude", "Error Budget" );
     310            0 :     m_indiP_mag.add( pcf::IndiElement( "current", 0 ) );
     311              : 
     312            0 :     CREATE_REG_INDI_RO_NUMBER( m_indiP_strehl, "strehl_optimal", "Strehl", "Error Budget" );
     313            0 :     m_indiP_strehl.add( pcf::IndiElement( "pyramid", 0 ) );
     314              : 
     315            0 :     CREATE_REG_INDI_RO_NUMBER( m_indiP_wfe, "wfe_predicted", "WFE", "Error Budget" );
     316            0 :     m_indiP_wfe.add( pcf::IndiElement( "total", 0 ) );
     317            0 :     m_indiP_wfe.add( pcf::IndiElement( "measurement", 0 ) );
     318            0 :     m_indiP_wfe.add( pcf::IndiElement( "time_delay", 0 ) );
     319            0 :     m_indiP_wfe.add( pcf::IndiElement( "fitting", 0 ) );
     320              : 
     321            0 :     state( stateCodes::OPERATING );
     322              : 
     323            0 :     return 0;
     324              : }
     325              : 
     326            0 : int strehlEstimator::appLogic()
     327              : {
     328            0 :     SHMIMMONITORT_APP_LOGIC( wfsavgShmimMonitorT );
     329            0 :     SHMIMMONITORT_APP_LOGIC( wfsmaskShmimMonitorT );
     330              : 
     331            0 :     SHMIMMONITORT_UPDATE_INDI( wfsavgShmimMonitorT );
     332            0 :     SHMIMMONITORT_UPDATE_INDI( wfsmaskShmimMonitorT );
     333              : 
     334            0 :     m_aosys.starMag( m_mag );
     335            0 :     m_aosys.F0( m_qe * m_F0 );
     336            0 :     m_aosys.lam_wfs( m_lam0 * 1e-6 );
     337            0 :     m_aosys.lam_sci( m_lam0 * 1e-6 );
     338            0 :     m_aosys.ron_wfs( std::vector<float>( { 245.0f / m_emg } ) );
     339            0 :     m_aosys.npix_wfs( std::vector<float>( { 1.0f * m_npix } ) );
     340            0 :     m_aosys.minTauWFS( std::vector<float>( { 1.0f / m_fps } ) );
     341            0 :     m_aosys.tauWFS( 1. / m_fps );
     342            0 :     m_aosys.atm.r_0( m_r0, 0.5e-6 );
     343            0 :     m_aosys.zeta( ( 90. - m_elevation ) * 3.14159 / 180. );
     344              : 
     345            0 :     updateIfChanged( m_indiP_strehl, "pyramid", m_aosys.strehl() );
     346            0 :     updatesIfChanged<double>( m_indiP_wfe,
     347              :                               { "total", "measurement", "time_delay", "fitting" },
     348            0 :                               { sqrt( m_aosys.wfeVar() ) * ( 1000 * m_lam0 / two_pi<float>() ),
     349            0 :                                 sqrt( m_aosys.measurementErrorTotal() ) * ( 1000 * m_lam0 / two_pi<float>() ),
     350            0 :                                 sqrt( m_aosys.timeDelayErrorTotal() ) * ( 1000 * m_lam0 / two_pi<float>() ),
     351            0 :                                 sqrt( m_aosys.fittingErrorTotal() ) * ( 1000 * m_lam0 / two_pi<float>() ) } );
     352            0 :     return 0;
     353              : }
     354              : 
     355            0 : int strehlEstimator::appShutdown()
     356              : {
     357            0 :     SHMIMMONITORT_APP_SHUTDOWN( wfsavgShmimMonitorT );
     358            0 :     SHMIMMONITORT_APP_SHUTDOWN( wfsmaskShmimMonitorT );
     359              : 
     360            0 :     return 0;
     361              : }
     362              : 
     363            0 : int strehlEstimator::allocate( const wfsavgShmimT &dummy )
     364              : {
     365              :     static_cast<void>( dummy );
     366              : 
     367            0 :     std::cerr << "Got WFS avg: " << wfsavgShmimMonitorT::m_width << " x " << wfsavgShmimMonitorT::m_height << '\n';
     368            0 :     return 0;
     369              : }
     370              : 
     371            0 : int strehlEstimator::processImage( void *curr_src, const wfsavgShmimT &dummy )
     372              : {
     373              :     static_cast<void>( dummy );
     374              : 
     375            0 :     m_wfsavg = mx::improc::eigenMap<float>(
     376            0 :         reinterpret_cast<float *>( curr_src ), wfsavgShmimMonitorT::m_width, wfsavgShmimMonitorT::m_height );
     377              : 
     378            0 :     if( m_wfsavg.rows() == m_wfsmask.rows() && m_wfsavg.cols() == m_wfsmask.cols() )
     379              :     {
     380            0 :         m_counts = ( m_wfsavg * m_wfsmask ).sum();
     381              : 
     382            0 :         std::cerr << "counts: " << m_counts << '\n';
     383              : 
     384            0 :         calcMag();
     385              :     }
     386              : 
     387            0 :     return 0;
     388              : }
     389              : 
     390            0 : int strehlEstimator::allocate( const wfsmaskShmimT &dummy )
     391              : {
     392              :     static_cast<void>( dummy );
     393              : 
     394            0 :     std::cerr << "Got WFS mask: " << wfsmaskShmimMonitorT::m_width << " x " << wfsmaskShmimMonitorT::m_height << '\n';
     395            0 :     return 0;
     396              : }
     397              : 
     398            0 : int strehlEstimator::processImage( void *curr_src, const wfsmaskShmimT &dummy )
     399              : {
     400              :     static_cast<void>( dummy );
     401              : 
     402            0 :     m_wfsmask = mx::improc::eigenMap<float>(
     403            0 :         reinterpret_cast<float *>( curr_src ), wfsmaskShmimMonitorT::m_width, wfsmaskShmimMonitorT::m_height );
     404              : 
     405            0 :     m_npix = m_wfsmask.sum();
     406              : 
     407            0 :     if( m_wfsavg.rows() == m_wfsmask.rows() && m_wfsavg.cols() == m_wfsmask.cols() )
     408              :     {
     409              :         // update counts because we might have been waiting on this.
     410            0 :         m_counts = ( m_wfsavg * m_wfsmask ).sum();
     411              : 
     412            0 :         calcMag();
     413              :     }
     414              : 
     415            0 :     return 0;
     416              : }
     417              : 
     418            0 : void strehlEstimator::calcMag()
     419              : {
     420            0 :     std::cerr << "calcMag: " << m_counts << ' ' << m_again << ' ' << ' ' << m_emg << ' ' << m_fps << ' ' << m_qe << ' '
     421            0 :               << m_F0 << '\n';
     422              : 
     423            0 :     m_mag = -2.5 * log10( m_counts * m_again / m_emg * m_fps / ( m_qe * m_F0 ) );
     424              : 
     425            0 :     updateIfChanged( m_indiP_mag, "current", m_mag );
     426            0 : }
     427              : 
     428            0 : INDI_SETCALLBACK_DEFN( strehlEstimator, m_indiP_fps )( const pcf::IndiProperty &ipRecv )
     429              : {
     430            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_fps, ipRecv );
     431              : 
     432            0 :     if( ipRecv.find( "current" ) )
     433              :     {
     434            0 :         float fps = ipRecv["current"].get<float>();
     435              : 
     436            0 :         if( fps != m_fps )
     437              :         {
     438            0 :             m_fps = fps;
     439            0 :             std::cerr << "Got FPS: " << m_fps << '\n';
     440              : 
     441            0 :             calcMag();
     442              :         }
     443              :     }
     444            0 :     return 0;
     445              : }
     446              : 
     447            0 : INDI_SETCALLBACK_DEFN( strehlEstimator, m_indiP_emg )( const pcf::IndiProperty &ipRecv )
     448              : {
     449            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_emg, ipRecv );
     450              : 
     451            0 :     if( ipRecv.find( "current" ) )
     452              :     {
     453            0 :         float emg = ipRecv["current"].get<float>();
     454              : 
     455            0 :         if( emg != m_emg )
     456              :         {
     457            0 :             m_emg = emg;
     458            0 :             std::cerr << "Got EMG: " << m_emg << '\n';
     459              : 
     460            0 :             calcMag();
     461              :         }
     462              :     }
     463            0 :     return 0;
     464              : }
     465              : 
     466            0 : INDI_SETCALLBACK_DEFN( strehlEstimator, m_indiP_stage )( const pcf::IndiProperty &ipRecv )
     467              : {
     468            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_stage, ipRecv );
     469              : 
     470              :     // if( ipRecv.find( "presetName" ) )
     471              :     {
     472            0 :         std::string preset = "none";
     473              : 
     474            0 :         for( auto &&el : ipRecv.getElements() )
     475              :         {
     476            0 :             if( el.second.getSwitchState() == pcf::IndiElement::On )
     477              :             {
     478            0 :                 preset = el.first;
     479            0 :                 break;
     480              :             }
     481              :         }
     482              : 
     483            0 :         std::cerr << "Got stage bs: " << preset << '\n';
     484              : 
     485            0 :         if( preset == "ha-ir" )
     486              :         {
     487            0 :             m_F0   = m_F0_HaIR;
     488            0 :             m_lam0 = m_lam0_HaIR;
     489            0 :             m_qe   = m_qe_HaIR;
     490              :         }
     491              :         else
     492              :         {
     493            0 :             m_F0   = m_F0_6535;
     494            0 :             m_lam0 = m_lam0_6535;
     495            0 :             m_qe   = m_qe_6535;
     496              :         }
     497              : 
     498            0 :         calcMag();
     499            0 :     }
     500              : 
     501            0 :     return 0;
     502              : }
     503              : 
     504            0 : INDI_SETCALLBACK_DEFN( strehlEstimator, m_indiP_tcsi_seeing )( const pcf::IndiProperty &ipRecv )
     505              : {
     506            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_tcsi_seeing, ipRecv );
     507              : 
     508            0 :     if( ipRecv.find( "dimm_fwhm_corr" ) )
     509              :     {
     510            0 :         float seeing = ipRecv["dimm_fwhm_corr"].get<float>();
     511              : 
     512            0 :         if( seeing != m_seeing )
     513              :         {
     514            0 :             m_seeing = seeing;
     515            0 :             std::cerr << "Got seeing: " << m_seeing << '\n';
     516              : 
     517            0 :             m_r0 = 0.2063 * 0.5 / m_seeing;
     518              :         }
     519              :     }
     520              : 
     521            0 :     return 0;
     522              : }
     523              : 
     524            0 : INDI_SETCALLBACK_DEFN( strehlEstimator, m_indiP_tcsi_telpos )( const pcf::IndiProperty &ipRecv )
     525              : {
     526            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_tcsi_telpos, ipRecv );
     527              : 
     528            0 :     if( ipRecv.find( "el" ) )
     529              :     {
     530            0 :         float elevation = ipRecv["el"].get<float>();
     531              : 
     532            0 :         if( elevation != m_elevation )
     533              :         {
     534            0 :             m_elevation = elevation;
     535            0 :             std::cerr << "Got elevation: " << m_elevation << '\n';
     536              :         }
     537              :     }
     538            0 :     return 0;
     539              : }
     540              : 
     541              : } // namespace app
     542              : } // namespace MagAOX
     543              : 
     544              : #endif // strehlEstimator_hpp
        

Generated by: LCOV version 2.0-1