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

            Line data    Source code
       1              : /** \file refRMS.hpp
       2              :   * \brief The MagAO-X user gain control app
       3              :   *
       4              :   * \ingroup app_files
       5              :   */
       6              : 
       7              : #ifndef refRMS_hpp
       8              : #define refRMS_hpp
       9              : 
      10              : #include <limits>
      11              : 
      12              : #include <mx/improc/eigenCube.hpp>
      13              : #include <mx/improc/eigenImage.hpp>
      14              : 
      15              : #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
      16              : #include "../../magaox_git_version.h"
      17              : 
      18              : namespace MagAOX
      19              : {
      20              : namespace app
      21              : {
      22              : 
      23              : struct refShmimT
      24              : {
      25            0 :    static std::string configSection()
      26              :    {
      27            0 :       return "refShmim";
      28              :    };
      29              : 
      30            0 :    static std::string indiPrefix()
      31              :    {
      32            0 :       return "refShmim";
      33              :    };
      34              : };
      35              : 
      36              : 
      37              : struct maskShmimT
      38              : {
      39            0 :    static std::string configSection()
      40              :    {
      41            0 :       return "maskShmim";
      42              :    };
      43              : 
      44            0 :    static std::string indiPrefix()
      45              :    {
      46            0 :       return "maskShmim";
      47              :    };
      48              : };
      49              : 
      50              : /** \defgroup refRMS Calculate the RMS of the ref subtracted image
      51              :   * \brief Calculates the r.m.s. of the reference subtracted WFS image.
      52              :   *
      53              :   * <a href="../handbook/operating/software/apps/refRMS.html">Application Documentation</a>
      54              :   *
      55              :   * \ingroup apps
      56              :   *
      57              :   */
      58              : 
      59              : /** \defgroup refRMS_files User Gain Control
      60              :   * \ingroup refRMS
      61              :   */
      62              : 
      63              : /** MagAO-X application to calculate the RMS of the reference subtracted WFS image.
      64              :   *
      65              :   * \ingroup refRMS
      66              :   *
      67              :   */
      68              : class refRMS : public MagAOXApp<true>, public dev::shmimMonitor<refRMS, refShmimT>,
      69              :                      public dev::shmimMonitor<refRMS,maskShmimT>
      70              : {
      71              : 
      72              :    //Give the test harness access.
      73              :    friend class refRMS_test;
      74              : 
      75              :    friend class dev::shmimMonitor<refRMS,refShmimT>;
      76              :    friend class dev::shmimMonitor<refRMS,maskShmimT>;
      77              : 
      78              : public:
      79              : 
      80              :    //The base shmimMonitor type
      81              :    typedef dev::shmimMonitor<refRMS,refShmimT> refShmimMonitorT;
      82              :    typedef dev::shmimMonitor<refRMS,maskShmimT> maskShmimMonitorT;
      83              : 
      84              :    ///Floating point type in which to do all calculations.
      85              :    typedef float realT;
      86              : 
      87              :    typedef int32_t cbIndexT;
      88              : 
      89              : protected:
      90              : 
      91              :    /** \name Configurable Parameters
      92              :      *@{
      93              :      */
      94              : 
      95              :    std::string m_fpsSource; ///< Device name for getting fps. This device should have *.fps.current.
      96              : 
      97              :    ///@}
      98              : 
      99              :    mx::improc::eigenImage<realT> m_currRef;
     100              :    mx::improc::eigenImage<realT> m_mask;
     101              :    bool m_maskValid {false};
     102              :    realT m_maskSum {0};
     103              : 
     104              :    mx::sigproc::circularBufferIndex<float, cbIndexT> m_rms;
     105              : 
     106              :    mx::sigproc::circularBufferIndex<float, cbIndexT> m_mean;
     107              : 
     108              :    double m_rms_1sec;
     109              :    double m_rms_2sec;
     110              :    double m_rms_5sec;
     111              :    double m_rms_10sec;
     112              : 
     113              :    float m_fps {0}; ///< Current FPS from the FPS source.
     114              : 
     115              : public:
     116              :    /// Default c'tor.
     117              :    refRMS();
     118              : 
     119              :    /// D'tor, declared and defined for noexcept.
     120            0 :    ~refRMS() noexcept
     121            0 :    {}
     122              : 
     123              :    virtual void setupConfig();
     124              : 
     125              :    /// Implementation of loadConfig logic, separated for testing.
     126              :    /** This is called by loadConfig().
     127              :      */
     128              :    int loadConfigImpl( mx::app::appConfigurator & _config /**< [in] an application configuration from which to load values*/);
     129              : 
     130              :    virtual void loadConfig();
     131              : 
     132              :    /// Startup function
     133              :    /**
     134              :      *
     135              :      */
     136              :    virtual int appStartup();
     137              : 
     138              :    /// Implementation of the FSM for refRMS.
     139              :    /**
     140              :      * \returns 0 on no critical error
     141              :      * \returns -1 on an error requiring shutdown
     142              :      */
     143              :    virtual int appLogic();
     144              : 
     145              :    /// Shutdown the app.
     146              :    /**
     147              :      *
     148              :      */
     149              :    virtual int appShutdown();
     150              : 
     151              : protected:
     152              : 
     153              : 
     154              :    int allocate( const refShmimT & dummy /**< [in] tag to differentiate shmimMonitor parents.*/);
     155              : 
     156              :    int processImage( void * curr_src,          ///< [in] pointer to start of current frame.
     157              :                      const refShmimT & dummy ///< [in] tag to differentiate shmimMonitor parents.
     158              :                    );
     159              : 
     160              : 
     161              :    int allocate( const maskShmimT & dummy /**< [in] tag to differentiate shmimMonitor parents.*/);
     162              : 
     163              :    int processImage( void * curr_src,          ///< [in] pointer to start of current frame.
     164              :                      const maskShmimT & dummy ///< [in] tag to differentiate shmimMonitor parents.
     165              :                    );
     166              : 
     167              : 
     168              :    pcf::IndiProperty m_indiP_refrms;
     169              : 
     170              :    pcf::IndiProperty m_indiP_fpsSource;
     171            0 :    INDI_SETCALLBACK_DECL(refRMS, m_indiP_fpsSource);
     172              : 
     173              : 
     174              : };
     175              : 
     176              : inline
     177              : refRMS::refRMS() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
     178              : {
     179              : 
     180              :    refShmimMonitorT::m_getExistingFirst = true;
     181              :    maskShmimMonitorT::m_getExistingFirst = true;
     182              : 
     183              :    return;
     184              : }
     185              : 
     186              : inline
     187            0 : void refRMS::setupConfig()
     188              : {
     189            0 :    refShmimMonitorT::setupConfig(config);
     190            0 :    maskShmimMonitorT::setupConfig(config);
     191              : 
     192            0 :    config.add("rms.fpsSource", "", "rms.fpsSource", argType::Required, "rms", "fpsSource", false, "string", "Device name for getting fps.  This device should have *.fps.current.");
     193            0 : }
     194              : 
     195              : inline
     196            0 : int refRMS::loadConfigImpl( mx::app::appConfigurator & _config )
     197              : {
     198            0 :    refShmimMonitorT::loadConfig(config);
     199              : 
     200            0 :    maskShmimMonitorT::loadConfig(config);
     201              : 
     202            0 :    _config(m_fpsSource, "rms.fpsSource");
     203              : 
     204            0 :    return 0;
     205              : }
     206              : 
     207              : inline
     208            0 : void refRMS::loadConfig()
     209              : {
     210            0 :    loadConfigImpl(config);
     211            0 : }
     212              : 
     213              : inline
     214            0 : int refRMS::appStartup()
     215              : {
     216            0 :    createROIndiNumber( m_indiP_refrms, "refrms", "Reference RMS", "");
     217            0 :    indi::addNumberElement(m_indiP_refrms, "one_sec", 0, 1, 1000, "One Second rms");
     218            0 :    indi::addNumberElement(m_indiP_refrms, "two_sec", 0, 1, 1000, "Two Second rms");
     219            0 :    indi::addNumberElement(m_indiP_refrms, "five_sec", 0, 1, 1000, "Five Second rms");
     220            0 :    indi::addNumberElement(m_indiP_refrms, "ten_sec", 0, 1, 1000, "Five Second rms");
     221            0 :    registerIndiPropertyReadOnly(m_indiP_refrms);
     222              : 
     223            0 :    if(m_fpsSource != "")
     224              :    {
     225            0 :       REG_INDI_SETPROP(m_indiP_fpsSource, m_fpsSource, std::string("fps"));
     226              :    }
     227              : 
     228            0 :    if(refShmimMonitorT::appStartup() < 0)
     229              :    {
     230            0 :       return log<software_error,-1>({__FILE__, __LINE__});
     231              :    }
     232              : 
     233            0 :    if(maskShmimMonitorT::appStartup() < 0)
     234              :    {
     235            0 :       return log<software_error,-1>({__FILE__, __LINE__});
     236              :    }
     237              : 
     238            0 :    state(stateCodes::OPERATING);
     239              : 
     240            0 :    return 0;
     241              : }
     242              : 
     243              : inline
     244            0 : int refRMS::appLogic()
     245              : {
     246              : 
     247            0 :    if( refShmimMonitorT::appLogic() < 0)
     248              :    {
     249            0 :       return log<software_error,-1>({__FILE__,__LINE__});
     250              :    }
     251              : 
     252            0 :    if( maskShmimMonitorT::appLogic() < 0)
     253              :    {
     254            0 :       return log<software_error,-1>({__FILE__,__LINE__});
     255              :    }
     256              : 
     257            0 :    if( m_rms.size() > 0 )
     258              :    {
     259            0 :       if(m_rms.size() >= m_rms.maxEntries())
     260              :       {
     261            0 :          m_rms_1sec = 0;
     262            0 :          if(m_rms.size() > 1.0*m_fps)
     263              :          {
     264            0 :             int N = 0;
     265            0 :             for(size_t n=0; n < 1.0*m_fps; ++n)
     266              :             {
     267            0 :                m_rms_1sec += m_rms[n];
     268            0 :                ++N;
     269              :             }
     270            0 :             m_rms_1sec /= N;
     271              : 
     272            0 :             std::cerr << m_rms_1sec << " ";
     273              : 
     274              :          }
     275              : 
     276            0 :          m_rms_2sec = 0;
     277            0 :          if(m_rms.size() > 2.0*m_fps)
     278              :          {
     279            0 :             int N = 0;
     280            0 :             for(size_t n=0; n < 2.0*m_fps; ++n)
     281              :             {
     282            0 :                m_rms_2sec += m_rms[n];
     283            0 :                ++N;
     284              :             }
     285            0 :             m_rms_2sec /= N;
     286              : 
     287            0 :             std::cerr << m_rms_2sec << " ";
     288              :          }
     289              : 
     290            0 :          m_rms_5sec = 0;
     291            0 :          if(m_rms.size() > 5.0*m_fps)
     292              :          {
     293            0 :             int N = 0;
     294            0 :             for(size_t n=0; n < 5.0*m_fps; ++n)
     295              :             {
     296            0 :                m_rms_5sec += m_rms[n];
     297            0 :                ++N;
     298              :             }
     299            0 :             m_rms_5sec /= N;
     300              : 
     301            0 :             std::cerr << m_rms_5sec << " ";
     302              :          }
     303              : 
     304            0 :          m_rms_10sec = 0;
     305            0 :          if(m_rms.size() > 10.0*m_fps)
     306              :          {
     307            0 :             int N = 0;
     308            0 :             for(size_t n=0; n < 10.0*m_fps; ++n)
     309              :             {
     310            0 :                m_rms_10sec += m_rms[n];
     311            0 :                ++N;
     312              :             }
     313            0 :             m_rms_10sec /= N;
     314              : 
     315            0 :             std::cerr << m_rms_10sec << " ";
     316              :          }
     317              : 
     318            0 :          std::cerr << "\n";
     319              : 
     320            0 :          updateIfChanged(m_indiP_refrms, std::vector<std::string>({"one_sec","two_sec","five_sec","ten_sec"}), std::vector<double>({m_rms_1sec, m_rms_2sec, m_rms_5sec, m_rms_10sec}));
     321              : 
     322              :       }
     323              :    }
     324              : 
     325              : 
     326            0 :    std::unique_lock<std::mutex> lock(m_indiMutex);
     327              : 
     328            0 :    if(refShmimMonitorT::updateINDI() < 0)
     329              :    {
     330            0 :       log<software_error>({__FILE__, __LINE__});
     331              :    }
     332              : 
     333            0 :    if(maskShmimMonitorT::updateINDI() < 0)
     334              :    {
     335            0 :       log<software_error>({__FILE__, __LINE__});
     336              :    }
     337              : 
     338            0 :    return 0;
     339            0 : }
     340              : 
     341              : inline
     342            0 : int refRMS::appShutdown()
     343              : {
     344            0 :    refShmimMonitorT::appShutdown();
     345            0 :    maskShmimMonitorT::appShutdown();
     346              : 
     347            0 :    return 0;
     348              : }
     349              : 
     350              : 
     351              : inline
     352            0 : int refRMS::allocate(const refShmimT & dummy)
     353              : {
     354              :    static_cast<void>(dummy); //be unused
     355              : 
     356            0 :    std::unique_lock<std::mutex> lock(m_indiMutex);
     357              : 
     358            0 :    m_currRef.resize(refShmimMonitorT::m_width, refShmimMonitorT::m_height);
     359              : 
     360            0 :    std::cerr << "got ref: " << refShmimMonitorT::m_width << " " << refShmimMonitorT::m_height << "\n";
     361              : 
     362            0 :    if(m_mask.rows() != m_currRef.rows() || m_mask.cols() != m_currRef.cols())
     363              :    {
     364            0 :       m_maskValid = false;
     365            0 :       m_mask.resize(m_currRef.rows(), m_currRef.cols());
     366            0 :       m_mask.setConstant(1);
     367              :    }
     368              : 
     369            0 :    while(m_fps == 0)
     370              :    {
     371            0 :       sleep(5);
     372              :       /*if(m_fps == 0)
     373              :       {
     374              :          return log<text_log,-1>("fps not updated", logPrio::LOG_ERROR);
     375              :       }*/
     376              :    }
     377              : 
     378            0 :    cbIndexT cbSz = 11 * m_fps;
     379            0 :    m_mean.maxEntries(cbSz);
     380            0 :    m_rms.maxEntries(cbSz);
     381              : 
     382            0 :    std::cerr << "allocated\n";
     383              : 
     384            0 :    return 0;
     385            0 : }
     386              : 
     387              : inline
     388            0 : int refRMS::processImage( void * curr_src,
     389              :                           const refShmimT & dummy
     390              :                         )
     391              : {
     392              :    static_cast<void>(dummy); //be unused
     393              : 
     394              :    //Copy it out first so we can afford to be slow and skipping frames
     395            0 :    m_currRef = Eigen::Map<Eigen::Matrix<float,-1,-1>>((float *)curr_src,  refShmimMonitorT::m_width, refShmimMonitorT::m_height);//,1);
     396              : 
     397              :    //std::cerr << "pi\n";
     398              : 
     399              :    //If mask has changed we skip
     400            0 :    if(m_mask.rows() != m_currRef.rows() || m_mask.cols() != m_currRef.cols())
     401              :    {
     402            0 :       std::cerr << m_mask.rows() << " " << m_mask.cols() << "\n";
     403            0 :       std::cerr << m_currRef.rows() << " " << m_currRef.cols() << "\n";
     404              : 
     405            0 :       return 0;
     406              :    }
     407              : 
     408              :    //mult by mask, etc.
     409            0 :    float mean = (m_currRef * m_mask).sum()/m_maskSum;
     410            0 :    float rms = sqrt(((m_currRef - mean)*m_mask).square().sum()/m_maskSum);
     411              : 
     412            0 :    m_mean.nextEntry(mean);
     413            0 :    m_rms.nextEntry(rms);
     414              : 
     415            0 :    return 0;
     416              : }
     417              : 
     418              : 
     419              : inline
     420            0 : int refRMS::allocate(const maskShmimT & dummy)
     421              : {
     422              :    static_cast<void>(dummy); //be unused
     423              : 
     424            0 :    std::unique_lock<std::mutex> lock(m_indiMutex);
     425              : 
     426            0 :    std::cerr << "got mask: " << maskShmimMonitorT::m_width << " " << maskShmimMonitorT::m_height << "\n";
     427              : 
     428            0 :    m_mask.resize(maskShmimMonitorT::m_width, maskShmimMonitorT::m_height);
     429              : 
     430            0 :    return 0;
     431            0 : }
     432              : 
     433              : inline
     434            0 : int refRMS::processImage( void * curr_src,
     435              :                           const maskShmimT & dummy
     436              :                         )
     437              : {
     438              :    static_cast<void>(dummy); //be unused
     439              : 
     440              :    //copy curr_src to mask
     441            0 :    m_mask = Eigen::Map<Eigen::Matrix<float,-1,-1>>((float *)curr_src,  maskShmimMonitorT::m_width,maskShmimMonitorT::m_height);
     442              : 
     443            0 :    m_maskSum = m_mask.sum();
     444              : 
     445            0 :    if(m_mask.rows() == m_currRef.rows() || m_mask.cols() == m_currRef.cols())
     446              :    {
     447            0 :       m_maskValid = true;
     448              :    }
     449              : 
     450            0 :    return 0;
     451              : }
     452              : 
     453            0 : INDI_SETCALLBACK_DEFN( refRMS, m_indiP_fpsSource )(const pcf::IndiProperty &ipRecv)
     454              : {
     455            0 :    if( ipRecv.getName() != m_indiP_fpsSource.getName())
     456              :    {
     457            0 :       log<software_error>({__FILE__, __LINE__, "Invalid INDI property."});
     458            0 :       return -1;
     459              :    }
     460              : 
     461            0 :    if( ipRecv.find("current") != true ) //this isn't valie
     462              :    {
     463            0 :       return 0;
     464              :    }
     465              : 
     466              :    //std::lock<std::mutex> mut(m_indiMutex);
     467              : 
     468            0 :    realT fps = ipRecv["current"].get<float>();
     469              :    //mut.unlock();
     470              : 
     471            0 :    if(fps != m_fps)
     472              :    {
     473            0 :       m_fps = fps;
     474            0 :       std::cout << "Got fps: " << m_fps << "\n";
     475            0 :       refShmimMonitorT::m_restart = true;
     476              :    }
     477              : 
     478            0 :    return 0;
     479              : }
     480              : 
     481              : } //namespace app
     482              : } //namespace MagAOX
     483              : 
     484              : #endif //refRMS_hpp
        

Generated by: LCOV version 2.0-1