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

            Line data    Source code
       1              : /** \file psfFit.hpp
       2              :  * \brief The MagAO-X PSF Fitter application header
       3              :  *
       4              :  * \ingroup psfFit_files
       5              :  */
       6              : 
       7              : #ifndef psfFit_hpp
       8              : #define psfFit_hpp
       9              : 
      10              : #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
      11              : #include "../../magaox_git_version.h"
      12              : 
      13              : /** \defgroup psfFit
      14              :  * \brief The MagAO-X PSF fitter.
      15              :  *
      16              :  * <a href="../handbook/operating/software/apps/psfFit.html">Application Documentation</a>
      17              :  *
      18              :  * \ingroup apps
      19              :  *
      20              :  */
      21              : 
      22              : /** \defgroup psfFit_files
      23              :  * \ingroup psfFit
      24              :  */
      25              : 
      26              : namespace MagAOX
      27              : {
      28              : namespace app
      29              : {
      30              : 
      31              : struct darkShmimT
      32              : {
      33            0 :     static std::string configSection()
      34              :     {
      35            0 :         return "darkShmim";
      36              :     };
      37              : 
      38            0 :     static std::string indiPrefix()
      39              :     {
      40            0 :         return "dark";
      41              :     };
      42              : };
      43              : 
      44              : struct refShmimT
      45              : {
      46            0 :     static std::string configSection()
      47              :     {
      48            0 :         return "refShmim";
      49              :     };
      50              : 
      51            0 :     static std::string indiPrefix()
      52              :     {
      53            0 :         return "ref";
      54              :     };
      55              : };
      56              : 
      57              : /// The MagAO-X PSF Fitter
      58              : /**
      59              :  * \ingroup psfFit
      60              :  */
      61              : class psfFit : public MagAOXApp<true>,
      62              :                public dev::shmimMonitor<psfFit>,
      63              :                public dev::shmimMonitor<psfFit, darkShmimT>,
      64              :                public dev::shmimMonitor<psfFit, refShmimT>,
      65              :                public dev::frameGrabber<psfFit>,
      66              :                public dev::telemeter<psfFit>
      67              : {
      68              :     // Give the test harness access.
      69              :     friend class psfFit_test;
      70              : 
      71              :     friend class dev::shmimMonitor<psfFit>;
      72              :     friend class dev::shmimMonitor<psfFit, darkShmimT>;
      73              :     friend class dev::shmimMonitor<psfFit, refShmimT>;
      74              :     friend class dev::frameGrabber<psfFit>;
      75              : 
      76              :     friend class dev::telemeter<psfFit>;
      77              : 
      78              :   public:
      79              :     /// The base shmimMonitor type
      80              :     typedef dev::shmimMonitor<psfFit> shmimMonitorT;
      81              : 
      82              :     /// The dark shmimMonitor type
      83              :     typedef dev::shmimMonitor<psfFit, darkShmimT> darkShmimMonitorT;
      84              : 
      85              :     /// The reference shmimMonitor type
      86              :     typedef dev::shmimMonitor<psfFit, refShmimT> refShmimMonitorT;
      87              : 
      88              :     // The base frameGrabber type
      89              :     typedef dev::frameGrabber<psfFit> frameGrabberT;
      90              : 
      91              :     // The base telemeter type
      92              :     typedef dev::telemeter<psfFit> telemeterT;
      93              : 
      94              :     /// Floating point type in which to do all calculations.
      95              :     typedef float realT;
      96              : 
      97              :     /** \name app::dev Configurations
      98              :      *@{
      99              :      */
     100              : 
     101              :     static constexpr bool c_frameGrabber_flippable =
     102              :         false; ///< app:dev config to tell framegrabber these images can not be flipped
     103              : 
     104              :     ///@}
     105              : 
     106              :   protected:
     107              :     /** \name Configurable Parameters
     108              :      *@{
     109              :      */
     110              : 
     111              :     std::string m_fpsDevice;               ///< Device name for getting fps to set circular buffer length.
     112              :     std::string m_fpsProperty{ "fps" };    ///< Property name for getting fps to set circular buffer length.
     113              :     std::string m_fpsElement{ "current" }; ///< Element name for getting fps to set circular buffer length.
     114              : 
     115              :     float m_fpsTol{ 0 }; ///< The tolerance for detecting a change in FPS.
     116              : 
     117              :     // shutter a change in shutter state resets stats
     118              :     std::string m_shutterDevice;                ///< Device name for getting shutter state
     119              :     std::string m_shutterProperty{ "shutter" }; ///< Property name for getting shutter state
     120              :     std::string m_shutterElement{ "toggle" };   ///< Element name for getting shutter state
     121              : 
     122              :     uint16_t m_fitCircBuffMaxLength{ 5 * 10000 }; ///< Maximum length of the latency measurement circular buffers
     123              : 
     124              :     float m_fitCircBuffMaxTime{ 5 }; ///< Maximum time of the latency meaurement circular buffers
     125              : 
     126              :     float m_deltaPixThresh{ 8 }; /**< Threshold in pixels for skipping frame due to mismatch between max and c.o.l.
     127              :                                       Default 2.*/
     128              : 
     129              :     float m_sigmaMaxThreshUp{ 5 }; /**< Threshold in rms for skipping frame due to max positive difference from mean
     130              :                                       max. Default 5.*/
     131              : 
     132              :     float m_fractionMaxThreshDown{ 0.1 }; /**< Threshold in fraction of the mean max for skipping frame due to
     133              :                                               drop from mean max. Default 0.1*/
     134              : 
     135              :     float m_sigmaPixThresh{ 10 }; /**< Threshold in rms for skipping frame due to max difference from last value.
     136              :                                      Example: if this is set to 10, then the pixel postion has to change from -5 sigma
     137              :                                      to + 5 sigma to be rejected. Default 10.*/
     138              : 
     139              :     ///@}
     140              : 
     141              :     mx::improc::eigenImage<float> m_image; ///< Holds the raw image
     142              : 
     143              :     mx::improc::eigenImage<float> m_dark; ///< Holds the dark image
     144              : 
     145              :     mx::improc::eigenImage<float> m_ref; ///< Holds the reference image
     146              : 
     147              :     bool m_updated{ false }; ///< Indicates that the coordinates were updated was updated
     148              : 
     149              :     bool m_skipped{ false }; ///< Indicates that the image failed quality control and this is a skip frame
     150              : 
     151              :     float m_x{ 0 };      ///< The current x coordinate
     152              :     float m_last_x{ 0 }; ///< The previous x coordinate
     153              : 
     154              :     float m_y{ 0 };      ///< The current y coordinate
     155              :     float m_last_y{ 0 }; ///< The previous y coordinate
     156              : 
     157              :     float m_dx{ 0 }; ///< The offset in x to apply to non-skipped measurements
     158              :     float m_dy{ 0 }; ///< The offset in y to apply to non-skipped measurements
     159              : 
     160              :     float m_fps{ 0 }; ///< The frame rate from the source camera
     161              : 
     162              :     bool m_shutter{ false };
     163              : 
     164              :     mx::sigproc::circularBufferIndex<float, cbIndexT> m_pcb; ///< Circular buffer for max pixel (p=peak)
     165              :     mx::sigproc::circularBufferIndex<float, cbIndexT> m_xcb; ///< Circular buffer for x COL coords
     166              :     mx::sigproc::circularBufferIndex<float, cbIndexT> m_ycb; ///< Circular buffer for y COL coords
     167              : 
     168              :     std::vector<float> m_pcbD; ///< Vector for doing calcs on max pixel
     169              :     std::vector<float> m_xcbD; ///< Vector for doing calcs on x COL coords
     170              :     std::vector<float> m_ycbD; ///< Vector for doing calcs on y COL coords
     171              : 
     172              :     float m_mnp{ 0 };  ///< The mean max pixel over the stats time
     173              :     float m_rmsp{ 0 }; ///< The rms max pixel over the stats time
     174              : 
     175              :     float m_mnx{ 0 };  ///< The mean x coord over the stats time
     176              :     float m_rmsx{ 0 }; ///< The rms x coord over the stats time
     177              :     float m_mny{ 0 };  ///< The mean y coord over the stats time
     178              :     float m_rmsy{ 0 }; ///< The rms y coord over the stats time
     179              : 
     180              :     uint64_t m_skipped_updating{ 0 };
     181              :     uint64_t m_skipped_updating_last{ 0 };
     182              : 
     183              :     uint64_t m_skipped_DeltaFromMax{ 0 };
     184              :     uint64_t m_skipped_DeltaFromMax_last{ 0 };
     185              : 
     186              :     uint64_t m_skipped_MaxRmsUp{ 0 };
     187              :     uint64_t m_skipped_MaxRmsUp_last{ 0 };
     188              : 
     189              :     uint64_t m_skipped_MaxRmsDown{ 0 };
     190              :     uint64_t m_skipped_MaxRmsDown_last{ 0 };
     191              : 
     192              :     uint64_t m_skipped_XRms{ 0 };
     193              :     uint64_t m_skipped_XRms_last{ 0 };
     194              : 
     195              :     uint64_t m_skipped_YRms{ 0 };
     196              :     uint64_t m_skipped_YRms_last{ 0 };
     197              : 
     198              :   public:
     199              :     /// Default c'tor.
     200              :     psfFit();
     201              : 
     202              :     /// D'tor, declared and defined for noexcept.
     203              :     ~psfFit() noexcept;
     204              : 
     205              :     virtual void setupConfig();
     206              : 
     207              :     /// Implementation of loadConfig logic, separated for testing.
     208              :     /** This is called by loadConfig().
     209              :      */
     210              :     int loadConfigImpl(
     211              :         mx::app::appConfigurator &_config /**< [in] an application configuration from which to load values*/ );
     212              : 
     213              :     virtual void loadConfig();
     214              : 
     215              :     /// Startup function
     216              :     /**
     217              :      *
     218              :      */
     219              :     virtual int appStartup();
     220              : 
     221              :     /// Implementation of the FSM for psfFit.
     222              :     /**
     223              :      * \returns 0 on no critical error
     224              :      * \returns -1 on an error requiring shutdown
     225              :      */
     226              :     virtual int appLogic();
     227              : 
     228              :     /// Shutdown the app.
     229              :     /**
     230              :      *
     231              :      */
     232              :     virtual int appShutdown();
     233              : 
     234              :     // shmimMonitor interface:
     235              :     int allocate( const dev::shmimT & );
     236              : 
     237              :     int processImage( void *curr_src, const dev::shmimT & );
     238              : 
     239              :     // shmimMonitor interface for dark:
     240              :     int allocate( const darkShmimT & );
     241              : 
     242              :     int processImage( void *curr_src, const darkShmimT & );
     243              : 
     244              :     // shmimMonitor interface for reference:
     245              :     int allocate( const refShmimT & );
     246              : 
     247              :     int processImage( void *curr_src, const refShmimT & );
     248              : 
     249              :   protected:
     250              :     std::mutex m_imageMutex;
     251              : 
     252              :     sem_t m_smSemaphore{ 0 }; ///< Semaphore used to synchronize the fg thread and the sm thread.
     253              : 
     254              :   public:
     255              :     /** \name dev::frameGrabber interface
     256              :      *
     257              :      * @{
     258              :      */
     259              : 
     260              :     /// Implementation of the framegrabber configureAcquisition interface
     261              :     /**
     262              :      * \returns 0 on success
     263              :      * \returns -1 on error
     264              :      */
     265              :     int configureAcquisition();
     266              : 
     267              :     /// Implementation of the framegrabber fps interface
     268              :     /**
     269              :      * \todo this needs to infer the stream fps and return it
     270              :      */
     271            0 :     float fps()
     272              :     {
     273            0 :         return m_fps;
     274              :     }
     275              : 
     276              :     /// Implementation of the framegrabber startAcquisition interface
     277              :     /**
     278              :      * \returns 0 on success
     279              :      * \returns -1 on error
     280              :      */
     281              :     int startAcquisition();
     282              : 
     283              :     /// Implementation of the framegrabber acquireAndCheckValid interface
     284              :     /**
     285              :      * \returns 0 on success
     286              :      * \returns -1 on error
     287              :      */
     288              :     int acquireAndCheckValid();
     289              : 
     290              :     /// Implementation of the framegrabber loadImageIntoStream interface
     291              :     /**
     292              :      * \returns 0 on success
     293              :      * \returns -1 on error
     294              :      */
     295              :     int loadImageIntoStream( void *dest /**< [in] */ );
     296              : 
     297              :     /// Implementation of the framegrabber reconfig interface
     298              :     /**
     299              :      * \returns 0 on success
     300              :      * \returns -1 on error
     301              :      */
     302              :     int reconfig();
     303              : 
     304              :     ///@}
     305              : 
     306              :   protected:
     307              :     /** \name INDI
     308              :      * @{
     309              :      */
     310              : 
     311              :     pcf::IndiProperty m_indiP_values;
     312              : 
     313              :     pcf::IndiProperty m_indiP_reset;
     314            0 :     INDI_NEWCALLBACK_DECL( psfFit, m_indiP_reset );
     315              : 
     316              :     pcf::IndiProperty m_indiP_statsTime;
     317            0 :     INDI_NEWCALLBACK_DECL( psfFit, m_indiP_statsTime );
     318              : 
     319              :     pcf::IndiProperty m_indiP_deltaPixThresh;
     320            0 :     INDI_NEWCALLBACK_DECL( psfFit, m_indiP_deltaPixThresh );
     321              : 
     322              :     pcf::IndiProperty m_indiP_sigmaMaxThreshUp;
     323            0 :     INDI_NEWCALLBACK_DECL( psfFit, m_indiP_sigmaMaxThreshUp );
     324              : 
     325              :     pcf::IndiProperty m_indiP_fractionMaxThreshDown;
     326            0 :     INDI_NEWCALLBACK_DECL( psfFit, m_indiP_fractionMaxThreshDown );
     327              : 
     328              :     pcf::IndiProperty m_indiP_sigmaPixThresh;
     329            0 :     INDI_NEWCALLBACK_DECL( psfFit, m_indiP_sigmaPixThresh );
     330              : 
     331              :     pcf::IndiProperty m_indiP_dx;
     332            0 :     INDI_NEWCALLBACK_DECL( psfFit, m_indiP_dx );
     333              : 
     334              :     pcf::IndiProperty m_indiP_dy;
     335            0 :     INDI_NEWCALLBACK_DECL( psfFit, m_indiP_dy );
     336              : 
     337              :     pcf::IndiProperty m_indiP_fpsSource;
     338            0 :     INDI_SETCALLBACK_DECL( psfFit, m_indiP_fpsSource );
     339              : 
     340              :     pcf::IndiProperty m_indiP_shutter;
     341            0 :     INDI_SETCALLBACK_DECL( psfFit, m_indiP_shutter );
     342              : 
     343              :     ///@}
     344              : 
     345              :     /** \name Telemeter Interface
     346              :      *
     347              :      * @{
     348              :      */
     349              :     int checkRecordTimes();
     350              : 
     351              :     int recordTelem( const telem_fgtimings * );
     352              : 
     353              :     ///@}
     354              : };
     355              : 
     356              : inline psfFit::psfFit() : MagAOXApp( MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED )
     357              : {
     358              :     darkShmimMonitorT::m_getExistingFirst = true;
     359              :     refShmimMonitorT::m_getExistingFirst  = true;
     360              : 
     361              :     return;
     362              : }
     363              : 
     364            0 : inline psfFit::~psfFit() noexcept
     365              : {
     366            0 : }
     367              : 
     368            0 : inline void psfFit::setupConfig()
     369              : {
     370            0 :     SHMIMMONITOR_SETUP_CONFIG( config );
     371            0 :     SHMIMMONITORT_SETUP_CONFIG( darkShmimMonitorT, config );
     372            0 :     SHMIMMONITORT_SETUP_CONFIG( refShmimMonitorT, config );
     373            0 :     FRAMEGRABBER_SETUP_CONFIG( config );
     374            0 :     TELEMETER_SETUP_CONFIG( config );
     375              : 
     376            0 :     config.add( "fitter.fpsDevice",
     377              :                 "",
     378              :                 "fitter.fpsDevice",
     379              :                 argType::Required,
     380              :                 "fitter",
     381              :                 "fpsDevice",
     382              :                 false,
     383              :                 "string",
     384              :                 "Device name for getting fps to set circular buffer length." );
     385            0 :     config.add( "fitter.fpsProperty",
     386              :                 "",
     387              :                 "fitter.fpsProperty",
     388              :                 argType::Required,
     389              :                 "fitter",
     390              :                 "fpsProperty",
     391              :                 false,
     392              :                 "string",
     393              :                 "Property name for getting fps to set circular buffer length. Default is 'fps'." );
     394            0 :     config.add( "fitter.fpsElement",
     395              :                 "",
     396              :                 "fitter.fpsElement",
     397              :                 argType::Required,
     398              :                 "fitter",
     399              :                 "fpsElement",
     400              :                 false,
     401              :                 "string",
     402              :                 "Property name for getting fps to set circular buffer length. Default is 'current'." );
     403            0 :     config.add( "fitter.fpsTol",
     404              :                 "",
     405              :                 "fitter.fpsTol",
     406              :                 argType::Required,
     407              :                 "fitter",
     408              :                 "fpsTol",
     409              :                 false,
     410              :                 "float",
     411              :                 "Tolerance for detecting a change in FPS.  Default is 0." );
     412            0 :     config.add( "fitter.defaultFPS",
     413              :                 "",
     414              :                 "fitter.defaultFPS",
     415              :                 argType::Required,
     416              :                 "fitter",
     417              :                 "defaultFPS",
     418              :                 false,
     419              :                 "realT",
     420              :                 "Default FPS at startup, will enable changing average length with psdTime before INDI available." );
     421              : 
     422            0 :     config.add( "fitter.shutterDevice",
     423              :                 "",
     424              :                 "fitter.shutterDevice",
     425              :                 argType::Required,
     426              :                 "fitter",
     427              :                 "shutterDevice",
     428              :                 false,
     429              :                 "string",
     430              :                 "Device name for getting shutter state to reset circular buffers" );
     431            0 :     config.add( "fitter.shutterProperty",
     432              :                 "",
     433              :                 "fitter.shutterProperty",
     434              :                 argType::Required,
     435              :                 "fitter",
     436              :                 "shutterProperty",
     437              :                 false,
     438              :                 "string",
     439              :                 "Property name for getting shutter state to reset circular buffers. Default is 'shutter'." );
     440            0 :     config.add( "fitter.shutterElement",
     441              :                 "",
     442              :                 "fitter.shutterElement",
     443              :                 argType::Required,
     444              :                 "fitter",
     445              :                 "shutterElement",
     446              :                 false,
     447              :                 "string",
     448              :                 "Property name for getting shutter state to reset circular buffers. Default is 'toggle'." );
     449              : 
     450            0 :     config.add( "fitter.deltaPixThresh",
     451              :                 "",
     452              :                 "fitter.deltaPixThresh",
     453              :                 argType::Required,
     454              :                 "fitter",
     455              :                 "deltaPixThresh",
     456              :                 false,
     457              :                 "float",
     458              :                 "Threshold in pixels for skipping frame due to mismatch between max and c.o.l.  Default 8." );
     459            0 :     config.add( "fitter.sigmaMaxThreshUp",
     460              :                 "",
     461              :                 "fitter.sigmaMaxThreshUp",
     462              :                 argType::Required,
     463              :                 "fitter",
     464              :                 "sigmaMaxThreshUp",
     465              :                 false,
     466              :                 "float",
     467              :                 "Threshold in rms for skipping frame due to max positive difference from mean max. Default 5." );
     468            0 :     config.add( "fitter.fractionMaxThreshDown",
     469              :                 "",
     470              :                 "fitter.fractionMaxThreshDown",
     471              :                 argType::Required,
     472              :                 "fitter",
     473              :                 "fractionMaxThreshDown",
     474              :                 false,
     475              :                 "float",
     476              :                 "Threshold in fraction of the mean max for skipping frame due to drop from mean max. Default 0.1" );
     477              : 
     478            0 :     config.add( "fitter.sigmaPixThresh",
     479              :                 "",
     480              :                 "fitter.sigmaPixThresh",
     481              :                 argType::Required,
     482              :                 "fitter",
     483              :                 "sigmaPixThresh",
     484              :                 false,
     485              :                 "float",
     486              :                 "Threshold in rms for skipping frame due to max difference from last value.  Example: if this is set "
     487              :                 "to 10, then the pixel postion has to change from -5 sigma to + 5 sigma to be rejected. Default 10." );
     488              : }
     489              : 
     490            0 : inline int psfFit::loadConfigImpl( mx::app::appConfigurator &_config )
     491              : {
     492            0 :     SHMIMMONITOR_LOAD_CONFIG( _config );
     493            0 :     SHMIMMONITORT_LOAD_CONFIG( darkShmimMonitorT, _config );
     494            0 :     SHMIMMONITORT_LOAD_CONFIG( refShmimMonitorT, _config );
     495              : 
     496            0 :     FRAMEGRABBER_LOAD_CONFIG( _config );
     497            0 :     TELEMETER_LOAD_CONFIG( _config );
     498              : 
     499            0 :     _config( m_fpsDevice, "fitter.fpsDevice" );
     500            0 :     _config( m_fpsProperty, "fitter.fpsProperty" );
     501            0 :     _config( m_fpsElement, "fitter.fpsElement" );
     502            0 :     _config( m_fpsTol, "fitter.fpsTol" );
     503            0 :     _config( m_fps, "fitter.defaultFPS" );
     504              : 
     505            0 :     _config( m_shutterDevice, "fitter.shutterDevice" );
     506            0 :     _config( m_shutterProperty, "fitter.shutterProperty" );
     507            0 :     _config( m_shutterElement, "fitter.shutterElement" );
     508              : 
     509            0 :     _config( m_deltaPixThresh, "fitter.deltaPixThresh" );
     510            0 :     _config( m_sigmaMaxThreshUp, "fitter.sigmaMaxThreshUp" );
     511            0 :     _config( m_fractionMaxThreshDown, "fitter.fractionMaxThreshDown" );
     512            0 :     _config( m_sigmaPixThresh, "fitter.sigmaPixThresh" );
     513              : 
     514            0 :     return 0;
     515              : }
     516              : 
     517            0 : inline void psfFit::loadConfig()
     518              : {
     519            0 :     loadConfigImpl( config );
     520            0 : }
     521              : 
     522            0 : inline int psfFit::appStartup()
     523              : {
     524            0 :     SHMIMMONITOR_APP_STARTUP;
     525            0 :     SHMIMMONITORT_APP_STARTUP( darkShmimMonitorT );
     526            0 :     SHMIMMONITORT_APP_STARTUP( refShmimMonitorT );
     527              : 
     528            0 :     if( sem_init( &m_smSemaphore, 0, 0 ) < 0 )
     529              :     {
     530            0 :         log<software_critical>( { __FILE__, __LINE__, errno, 0, "Initializing S.M. semaphore" } );
     531            0 :         return -1;
     532              :     }
     533              : 
     534            0 :     FRAMEGRABBER_APP_STARTUP;
     535            0 :     TELEMETER_APP_STARTUP;
     536              : 
     537            0 :     if( m_fpsDevice != "" && m_fpsProperty != "" )
     538              :     {
     539            0 :         REG_INDI_SETPROP( m_indiP_fpsSource, m_fpsDevice, m_fpsProperty );
     540              :     }
     541              : 
     542            0 :     if( m_shutterDevice != "" && m_shutterProperty != "" )
     543              :     {
     544            0 :         REG_INDI_SETPROP( m_indiP_shutter, m_shutterDevice, m_shutterProperty );
     545              :     }
     546              : 
     547            0 :     CREATE_REG_INDI_RO_NUMBER( m_indiP_values, "values", "", "" );
     548            0 :     m_indiP_values.add( pcf::IndiElement( "max_mean" ) );
     549            0 :     m_indiP_values.add( pcf::IndiElement( "max_rms" ) );
     550            0 :     m_indiP_values.add( pcf::IndiElement( "x_mean" ) );
     551            0 :     m_indiP_values.add( pcf::IndiElement( "x_rms" ) );
     552            0 :     m_indiP_values.add( pcf::IndiElement( "y_mean" ) );
     553            0 :     m_indiP_values.add( pcf::IndiElement( "y_rms" ) );
     554              : 
     555            0 :     CREATE_REG_INDI_NEW_REQUESTSWITCH( m_indiP_reset, "reset" );
     556              : 
     557            0 :     CREATE_REG_INDI_NEW_NUMBERF( m_indiP_statsTime, "statsTime", 0, 5, 1, "%0.1f", "", "" );
     558            0 :     m_indiP_statsTime["current"].setValue( m_fitCircBuffMaxTime );
     559            0 :     m_indiP_statsTime["target"].setValue( m_fitCircBuffMaxTime );
     560              : 
     561            0 :     CREATE_REG_INDI_NEW_NUMBERF( m_indiP_deltaPixThresh, "deltaPixThresh", 0, 512, 1, "%0.1f", "", "" );
     562            0 :     m_indiP_deltaPixThresh["current"].setValue( m_deltaPixThresh );
     563            0 :     m_indiP_deltaPixThresh["target"].setValue( m_deltaPixThresh );
     564              : 
     565            0 :     CREATE_REG_INDI_NEW_NUMBERF( m_indiP_sigmaMaxThreshUp, "sigmaMaxThreshUp", 0, 512, 1, "%0.1f", "", "" );
     566            0 :     m_indiP_sigmaMaxThreshUp["current"].setValue( m_sigmaMaxThreshUp );
     567            0 :     m_indiP_sigmaMaxThreshUp["target"].setValue( m_sigmaMaxThreshUp );
     568              : 
     569            0 :     CREATE_REG_INDI_NEW_NUMBERF( m_indiP_fractionMaxThreshDown, "fractionMaxThreshDown", 0, 512, 1, "%0.1f", "", "" );
     570            0 :     m_indiP_fractionMaxThreshDown["current"].setValue( m_fractionMaxThreshDown );
     571            0 :     m_indiP_fractionMaxThreshDown["target"].setValue( m_fractionMaxThreshDown );
     572              : 
     573            0 :     CREATE_REG_INDI_NEW_NUMBERF( m_indiP_sigmaPixThresh, "sigmaPixThresh", 0, 512, 1, "%0.1f", "", "" );
     574            0 :     m_indiP_sigmaPixThresh["current"].setValue( m_sigmaPixThresh );
     575            0 :     m_indiP_sigmaPixThresh["target"].setValue( m_sigmaPixThresh );
     576              : 
     577            0 :     CREATE_REG_INDI_NEW_NUMBERF( m_indiP_dx, "dx", -100, 100, 1e-2, "%0.02f", "", "" );
     578            0 :     m_indiP_dx["current"].setValue( m_dx );
     579            0 :     m_indiP_dx["target"].setValue( m_dx );
     580              : 
     581            0 :     CREATE_REG_INDI_NEW_NUMBERF( m_indiP_dy, "dy", -100, 100, 1e-2, "%0.02f", "", "" );
     582            0 :     m_indiP_dy["current"].setValue( m_dy );
     583            0 :     m_indiP_dy["target"].setValue( m_dy );
     584              : 
     585            0 :     state( stateCodes::OPERATING );
     586              : 
     587            0 :     return 0;
     588              : }
     589              : 
     590            0 : inline int psfFit::appLogic()
     591              : {
     592            0 :     SHMIMMONITOR_APP_LOGIC;
     593            0 :     SHMIMMONITORT_APP_LOGIC( darkShmimMonitorT );
     594            0 :     SHMIMMONITORT_APP_LOGIC( refShmimMonitorT );
     595            0 :     FRAMEGRABBER_APP_LOGIC;
     596            0 :     TELEMETER_APP_LOGIC;
     597              : 
     598            0 :     if( state() == stateCodes::OPERATING && m_xcb.size() > 0 )
     599              :     {
     600            0 :         if( m_xcb.maxEntries() > 2 && m_xcb.size() >= m_xcb.maxEntries() )
     601              :         {
     602            0 :             cbIndexT refEntry = m_xcb.earliest();
     603              : 
     604            0 :             m_pcbD.resize( m_pcb.maxEntries() - 1 );
     605            0 :             m_xcbD.resize( m_xcb.maxEntries() - 1 );
     606            0 :             m_ycbD.resize( m_xcb.maxEntries() - 1 );
     607              : 
     608            0 :             for( size_t n = 0; n < m_xcbD.size(); ++n )
     609              :             {
     610            0 :                 m_pcbD[n] = m_pcb.at( refEntry, n );
     611            0 :                 m_xcbD[n] = m_xcb.at( refEntry, n );
     612            0 :                 m_ycbD[n] = m_ycb.at( refEntry, n );
     613              :             }
     614              : 
     615            0 :             m_mnp  = mx::math::vectorMean( m_pcbD );
     616            0 :             m_rmsp = sqrt( mx::math::vectorVariance( m_pcbD, m_mnp ) );
     617              : 
     618            0 :             m_mnx = mx::math::vectorMean( m_xcbD );
     619              : 
     620            0 :             m_rmsx = sqrt( mx::math::vectorVariance( m_xcbD, m_mnx ) );
     621              : 
     622            0 :             m_mny  = mx::math::vectorMean( m_ycbD );
     623            0 :             m_rmsy = sqrt( mx::math::vectorVariance( m_ycbD, m_mny ) );
     624              :         }
     625              :         else
     626              :         {
     627            0 :             m_mnp  = 0;
     628            0 :             m_rmsp = 0;
     629              : 
     630            0 :             m_mnx  = 0;
     631            0 :             m_rmsx = 0;
     632              : 
     633            0 :             m_mny  = 0;
     634            0 :             m_rmsy = 0;
     635              :         }
     636              : 
     637            0 :         int skipped_updating     = m_skipped_updating - m_skipped_updating_last;
     638            0 :         int skipped_DeltaFromMax = m_skipped_DeltaFromMax - m_skipped_DeltaFromMax_last;
     639            0 :         int skipped_MaxRmsUp     = m_skipped_MaxRmsUp - m_skipped_MaxRmsUp_last;
     640            0 :         int skipped_MaxRmsDown   = m_skipped_MaxRmsDown - m_skipped_MaxRmsDown_last;
     641            0 :         int skipped_XRms         = m_skipped_XRms - m_skipped_XRms_last;
     642            0 :         int skipped_YRms         = m_skipped_YRms - m_skipped_YRms_last;
     643              : 
     644            0 :         if( skipped_updating || skipped_DeltaFromMax || skipped_MaxRmsUp || skipped_MaxRmsDown || skipped_XRms ||
     645              :             skipped_YRms )
     646              :         {
     647            0 :             std::cerr << "skipping frames: \n";
     648            0 :             std::cerr << "          updating: " << skipped_updating << '\n';
     649            0 :             std::cerr << "    delta-from-max: " << skipped_DeltaFromMax << '\n';
     650            0 :             std::cerr << "        max-rms-up: " << skipped_MaxRmsUp << '\n';
     651            0 :             std::cerr << "      max-rms-down: " << skipped_MaxRmsDown << '\n';
     652            0 :             std::cerr << "             x-rms: " << skipped_XRms << '\n';
     653            0 :             std::cerr << "             y-rms: " << skipped_YRms << '\n';
     654              :         }
     655            0 :         m_skipped_updating          = m_skipped_updating_last;
     656            0 :         m_skipped_DeltaFromMax_last = m_skipped_DeltaFromMax;
     657            0 :         m_skipped_MaxRmsUp_last     = m_skipped_MaxRmsUp;
     658            0 :         m_skipped_MaxRmsDown_last   = m_skipped_MaxRmsDown;
     659            0 :         m_skipped_XRms_last         = m_skipped_XRms;
     660            0 :         m_skipped_YRms_last         = m_skipped_YRms;
     661              :     }
     662              :     else
     663              :     {
     664            0 :         m_mnp  = 0;
     665            0 :         m_rmsp = 0;
     666              : 
     667            0 :         m_mnx  = 0;
     668            0 :         m_rmsx = 0;
     669              : 
     670            0 :         m_mny  = 0;
     671            0 :         m_rmsy = 0;
     672              :     }
     673              : 
     674            0 :     SHMIMMONITOR_UPDATE_INDI;
     675            0 :     SHMIMMONITORT_UPDATE_INDI( darkShmimMonitorT );
     676            0 :     SHMIMMONITORT_UPDATE_INDI( refShmimMonitorT );
     677            0 :     FRAMEGRABBER_UPDATE_INDI;
     678              : 
     679            0 :     updateIfChanged( m_indiP_statsTime, "current", m_fitCircBuffMaxTime );
     680              : 
     681            0 :     updatesIfChanged<float>( m_indiP_values,
     682              :                              { "max_mean", "max_rms", "x_mean", "x_rms", "y_mean", "y_rms" },
     683            0 :                              { m_mnp, m_rmsp, m_mnx, m_rmsx, m_mny, m_rmsy } );
     684              : 
     685            0 :     updateIfChanged( m_indiP_dx, "current", m_dx );
     686            0 :     updateIfChanged( m_indiP_dy, "current", m_dy );
     687              : 
     688              : 
     689            0 :     return 0;
     690              : }
     691              : 
     692            0 : inline int psfFit::appShutdown()
     693              : {
     694            0 :     SHMIMMONITOR_APP_SHUTDOWN;
     695            0 :     SHMIMMONITORT_APP_SHUTDOWN( darkShmimMonitorT );
     696            0 :     SHMIMMONITORT_APP_SHUTDOWN( refShmimMonitorT );
     697            0 :     FRAMEGRABBER_APP_SHUTDOWN;
     698            0 :     TELEMETER_APP_SHUTDOWN;
     699              : 
     700            0 :     return 0;
     701              : }
     702              : 
     703            0 : inline int psfFit::allocate( const dev::shmimT &dummy )
     704              : {
     705              :     static_cast<void>( dummy );
     706              : 
     707            0 :     std::lock_guard<std::mutex> guard( m_imageMutex );
     708              : 
     709            0 :     m_image.resize( shmimMonitorT::m_width, shmimMonitorT::m_height );
     710            0 :     m_image.setZero();
     711              : 
     712            0 :     if( m_fitCircBuffMaxLength == 0 || m_fitCircBuffMaxTime == 0 || m_fps <= 0 )
     713              :     {
     714            0 :         m_pcb.maxEntries( 0 );
     715            0 :         m_xcb.maxEntries( 0 );
     716            0 :         m_ycb.maxEntries( 0 );
     717              : 
     718            0 :         m_mnp  = 0;
     719            0 :         m_rmsp = 0;
     720              : 
     721            0 :         m_mnx  = 0;
     722            0 :         m_rmsx = 0;
     723              : 
     724            0 :         m_mny  = 0;
     725            0 :         m_rmsy = 0;
     726              :     }
     727              :     else
     728              :     {
     729              :         // Set up the fit circ. buffs
     730            0 :         cbIndexT cbSz = m_fitCircBuffMaxTime * m_fps+1;
     731            0 :         if( cbSz > m_fitCircBuffMaxLength )
     732              :         {
     733            0 :             cbSz = m_fitCircBuffMaxLength;
     734              :         }
     735            0 :         if( cbSz < 3 )
     736              :         {
     737            0 :             cbSz = 3; // Make variance meaningful
     738              :         }
     739              : 
     740            0 :         std::cerr << "Fit circ. buff size: " << cbSz << ' ' << m_fitCircBuffMaxTime << ' ' << m_fps << '\n';
     741            0 :         m_pcb.maxEntries( cbSz );
     742            0 :         m_xcb.maxEntries( cbSz );
     743            0 :         m_ycb.maxEntries( cbSz );
     744              : 
     745            0 :         m_mnp  = 0;
     746            0 :         m_rmsp = 0;
     747              : 
     748            0 :         m_mnx  = 0;
     749            0 :         m_rmsx = 0;
     750              : 
     751            0 :         m_mny  = 0;
     752            0 :         m_rmsy = 0;
     753              :     }
     754              : 
     755            0 :     m_updated = false;
     756            0 :     return 0;
     757            0 : }
     758              : 
     759            0 : inline int psfFit::processImage( void *curr_src, const dev::shmimT &dummy )
     760              : {
     761              :     static_cast<void>( dummy );
     762              : 
     763              :     // counters for managing printing of delta-pix skips when shutter closed
     764              :     // static int skip_interval = 10;
     765              :     // static int last_passed = skip_interval + 1;
     766              : 
     767            0 :     std::unique_lock<std::mutex> lock( m_imageMutex );
     768              : 
     769            0 :     if( m_dark.rows() == m_image.rows() && m_dark.cols() == m_image.cols() )
     770              :     {
     771            0 :         if( shmimMonitorT::m_dataType == _DATATYPE_UINT16 )
     772              :         {
     773            0 :             for( unsigned nn = 0; nn < shmimMonitorT::m_width * shmimMonitorT::m_height; ++nn )
     774              :             {
     775            0 :                 m_image.data()[nn] = ( reinterpret_cast<uint16_t *>( curr_src ) )[nn] - m_dark.data()[nn];
     776              :             }
     777              :         }
     778            0 :         else if( shmimMonitorT::m_dataType == _DATATYPE_FLOAT )
     779              :         {
     780            0 :             for( unsigned nn = 0; nn < shmimMonitorT::m_width * shmimMonitorT::m_height; ++nn )
     781              :             {
     782            0 :                 m_image.data()[nn] = ( reinterpret_cast<float *>( curr_src ) )[nn] - m_dark.data()[nn];
     783              :             }
     784              :         }
     785              :     }
     786              :     else
     787              :     {
     788            0 :         if( shmimMonitorT::m_dataType == _DATATYPE_UINT16 )
     789              :         {
     790            0 :             for( unsigned nn = 0; nn < shmimMonitorT::m_width * shmimMonitorT::m_height; ++nn )
     791              :             {
     792            0 :                 m_image.data()[nn] = ( reinterpret_cast<uint16_t *>( curr_src ) )[nn];
     793              :             }
     794              :         }
     795            0 :         else if( shmimMonitorT::m_dataType == _DATATYPE_FLOAT )
     796              :         {
     797            0 :             for( unsigned nn = 0; nn < shmimMonitorT::m_width * shmimMonitorT::m_height; ++nn )
     798              :             {
     799            0 :                 m_image.data()[nn] = ( reinterpret_cast<float *>( curr_src ) )[nn];
     800              :             }
     801              :         }
     802              :     }
     803              : 
     804            0 :     lock.unlock();
     805              : 
     806              :     float max;
     807            0 :     realT local_x = 0;
     808            0 :     realT local_y = 0;
     809            0 :     int   x       = 0;
     810            0 :     int   y       = 0;
     811              : 
     812            0 :     max = m_image.maxCoeff( &x, &y );
     813              : 
     814            0 :     mx::improc::imageCenterOfLight( local_x, local_y, m_image );
     815              : 
     816            0 :     bool local_skipped = false;
     817              : 
     818            0 :     if( m_shutter )
     819              :     {
     820            0 :         local_skipped = true; // silently skip when shutter closed
     821              :     }
     822              : 
     823            0 :     if( !local_skipped && ( fabs( local_x - x ) > m_deltaPixThresh || fabs( local_y - y ) > m_deltaPixThresh ) )
     824              :     {
     825            0 :         ++m_skipped_DeltaFromMax;
     826            0 :         local_skipped = true;
     827              : 
     828              :         // We do not add these measurements to stats b/c this means bad PSF
     829              :     }
     830              : 
     831              :     // still filling circular buffer
     832            0 :     if( !local_skipped && ( m_rmsx == 0 || m_rmsy == 0 || m_rmsp == 0 ) )
     833              :     {
     834            0 :         if( m_xcb.maxEntries() > 0 )
     835              :         {
     836            0 :             m_pcb.nextEntry( max );
     837            0 :             m_xcb.nextEntry( local_x );
     838            0 :             m_ycb.nextEntry( local_y );
     839              :         }
     840              : 
     841            0 :         m_last_x = local_x;
     842            0 :         m_last_y = local_y;
     843              : 
     844            0 :         local_skipped = true;
     845              :     }
     846              : 
     847              :     // The remaining checks are for wild motions but otherwise valid fits (good PSF)
     848              : 
     849            0 :     if( !local_skipped && ( ( max - m_mnp ) / m_rmsp > m_sigmaMaxThreshUp ) )
     850              :     {
     851            0 :         if( m_pcb.maxEntries() > 0 )
     852              :         {
     853            0 :             m_pcb.nextEntry( max );
     854            0 :             m_xcb.nextEntry( local_x );
     855            0 :             m_ycb.nextEntry( local_y );
     856              :         }
     857              : 
     858            0 :         m_last_x = local_x;
     859            0 :         m_last_y = local_y;
     860              : 
     861            0 :         ++m_skipped_MaxRmsUp;
     862            0 :         local_skipped = true;
     863              :     }
     864              : 
     865            0 :     if( !local_skipped && ( ( m_mnp - max ) / m_mnp > ( 1.0 - m_fractionMaxThreshDown ) ) )
     866              :     {
     867            0 :         if( m_pcb.maxEntries() > 0 )
     868              :         {
     869            0 :             m_pcb.nextEntry( max );
     870            0 :             m_xcb.nextEntry( local_x );
     871            0 :             m_ycb.nextEntry( local_y );
     872              :         }
     873              : 
     874            0 :         m_last_x = local_x;
     875            0 :         m_last_y = local_y;
     876              : 
     877            0 :         ++m_skipped_MaxRmsDown;
     878            0 :         local_skipped = true;
     879              :     }
     880              : 
     881            0 :     if( !local_skipped && ( fabs( local_x - m_last_x ) / m_rmsx > m_sigmaPixThresh ) )
     882              :     {
     883            0 :         if( m_xcb.maxEntries() > 0 )
     884              :         {
     885            0 :             m_pcb.nextEntry( max );
     886            0 :             m_xcb.nextEntry( local_x );
     887            0 :             m_ycb.nextEntry( local_y );
     888              :         }
     889              : 
     890            0 :         m_last_x = local_x;
     891            0 :         m_last_y = local_y;
     892              : 
     893            0 :         ++m_skipped_XRms;
     894            0 :         local_skipped = true;
     895              :     }
     896              : 
     897            0 :     if( !local_skipped && ( fabs( local_y - m_last_y ) / m_rmsy > m_sigmaPixThresh ) )
     898              :     {
     899            0 :         if( m_ycb.maxEntries() > 0 )
     900              :         {
     901            0 :             m_pcb.nextEntry( max );
     902            0 :             m_xcb.nextEntry( local_x );
     903            0 :             m_ycb.nextEntry( local_y );
     904              :         }
     905              : 
     906            0 :         ++m_skipped_YRms;
     907            0 :         m_last_x = local_x;
     908            0 :         m_last_y = local_y;
     909              : 
     910            0 :         local_skipped = true;
     911              :     }
     912              : 
     913            0 :     if( local_skipped )
     914              :     {
     915            0 :         if( m_ref.rows() == 2 && m_ref.cols() == 1 )
     916              :         {
     917            0 :             local_x = m_ref( 0, 0 );
     918            0 :             local_y = m_ref( 1, 0 );
     919              :         }
     920              :         else
     921              :         {
     922            0 :             local_x = 0;
     923            0 :             local_y = 0;
     924              :         }
     925              :     }
     926              : 
     927            0 :     if( m_updated == true ) // means the framegrabber hasn't posted the last one yet
     928              :     {
     929            0 :         ++m_skipped_updating;
     930            0 :         return 0;
     931              :     }
     932              : 
     933            0 :     m_skipped = local_skipped;
     934            0 :     m_x       = local_x;
     935            0 :     m_y       = local_y;
     936              : 
     937            0 :     m_updated = true;
     938              : 
     939              :     // signal framegrabber
     940              :     // Now tell the f.g. to get going
     941            0 :     if( sem_post( &m_smSemaphore ) < 0 )
     942              :     {
     943            0 :         log<software_critical>( { __FILE__, __LINE__, errno, 0, "Error posting to semaphore" } );
     944            0 :         return -1;
     945              :     }
     946              : 
     947            0 :     if( !m_skipped )
     948              :     {
     949            0 :         if( m_xcb.maxEntries() > 0 )
     950              :         {
     951            0 :             m_pcb.nextEntry( max );
     952            0 :             m_xcb.nextEntry( m_x );
     953            0 :             m_ycb.nextEntry( m_y );
     954              :         }
     955              : 
     956            0 :         m_last_x = m_x;
     957            0 :         m_last_y = m_y;
     958              :     }
     959              : 
     960            0 :     return 0;
     961            0 : }
     962              : 
     963            0 : int psfFit::allocate( const darkShmimT &dummy )
     964              : {
     965              :     static_cast<void>( dummy );
     966              : 
     967            0 :     std::lock_guard<std::mutex> guard( m_imageMutex );
     968              : 
     969            0 :     if( darkShmimMonitorT::m_dataType != IMAGESTRUCT_FLOAT )
     970              :     {
     971            0 :         return log<software_error, -1>( { __FILE__, __LINE__, "dark is not float" } );
     972              :     }
     973              : 
     974            0 :     m_dark.resize( darkShmimMonitorT::m_width, darkShmimMonitorT::m_height );
     975            0 :     m_dark.setZero();
     976              : 
     977            0 :     return 0;
     978            0 : }
     979              : 
     980            0 : int psfFit::processImage( void *curr_src, const darkShmimT &dummy )
     981              : {
     982              :     static_cast<void>( dummy );
     983              : 
     984            0 :     std::unique_lock<std::mutex> lock( m_imageMutex );
     985              : 
     986            0 :     for( unsigned nn = 0; nn < darkShmimMonitorT::m_width * darkShmimMonitorT::m_height; ++nn )
     987              :     {
     988            0 :         m_dark.data()[nn] = ( reinterpret_cast<float *>( curr_src ) )[nn];
     989              :     }
     990              : 
     991            0 :     lock.unlock();
     992              : 
     993            0 :     log<text_log>( "dark updated", logPrio::LOG_INFO );
     994              : 
     995            0 :     return 0;
     996            0 : }
     997              : 
     998            0 : int psfFit::allocate( const refShmimT &dummy )
     999              : {
    1000              :     static_cast<void>( dummy );
    1001              : 
    1002            0 :     std::lock_guard<std::mutex> guard( m_imageMutex );
    1003              : 
    1004            0 :     if( refShmimMonitorT::m_dataType != IMAGESTRUCT_FLOAT )
    1005              :     {
    1006            0 :         return log<software_error, -1>( { __FILE__, __LINE__, "ref is not float" } );
    1007              :     }
    1008              : 
    1009            0 :     m_ref.resize( refShmimMonitorT::m_width, refShmimMonitorT::m_height );
    1010            0 :     m_ref.setZero();
    1011              : 
    1012            0 :     return 0;
    1013            0 : }
    1014              : 
    1015            0 : int psfFit::processImage( void *curr_src, const refShmimT &dummy )
    1016              : {
    1017              :     static_cast<void>( dummy );
    1018              : 
    1019            0 :     std::unique_lock<std::mutex> lock( m_imageMutex );
    1020              : 
    1021            0 :     for( unsigned nn = 0; nn < refShmimMonitorT::m_width * refShmimMonitorT::m_height; ++nn )
    1022              :     {
    1023            0 :         m_ref.data()[nn] = ( reinterpret_cast<float *>( curr_src ) )[nn];
    1024              :     }
    1025              : 
    1026            0 :     lock.unlock();
    1027              : 
    1028            0 :     log<text_log>( "reference updated", logPrio::LOG_INFO );
    1029              : 
    1030            0 :     return 0;
    1031            0 : }
    1032              : 
    1033            0 : inline int psfFit::configureAcquisition()
    1034              : {
    1035              : 
    1036            0 :     frameGrabberT::m_width    = 2;
    1037            0 :     frameGrabberT::m_height   = 1;
    1038            0 :     frameGrabberT::m_dataType = _DATATYPE_FLOAT;
    1039              : 
    1040            0 :     return 0;
    1041              : }
    1042              : 
    1043            0 : inline int psfFit::startAcquisition()
    1044              : {
    1045            0 :     return 0;
    1046              : }
    1047              : 
    1048            0 : inline int psfFit::acquireAndCheckValid()
    1049              : {
    1050              :     timespec ts;
    1051              : 
    1052            0 :     if( clock_gettime( CLOCK_REALTIME, &ts ) < 0 )
    1053              :     {
    1054            0 :         log<software_critical>( { __FILE__, __LINE__, errno, 0, "clock_gettime" } );
    1055            0 :         return -1;
    1056              :     }
    1057              : 
    1058            0 :     ts.tv_sec += 1;
    1059              : 
    1060            0 :     if( sem_timedwait( &m_smSemaphore, &ts ) == 0 )
    1061              :     {
    1062            0 :         if( m_updated )
    1063              :         {
    1064            0 :             clock_gettime( CLOCK_REALTIME, &m_currImageTimestamp );
    1065            0 :             return 0;
    1066              :         }
    1067              :         else
    1068              :         {
    1069            0 :             return 1;
    1070              :         }
    1071              :     }
    1072              :     else
    1073              :     {
    1074            0 :         return 1;
    1075              :     }
    1076              : }
    1077              : 
    1078            0 : inline int psfFit::loadImageIntoStream( void *dest )
    1079              : {
    1080            0 :     if( !m_skipped )
    1081              :     {
    1082            0 :         ( reinterpret_cast<float *>( dest ) )[0] = m_x - m_dx;
    1083            0 :         ( reinterpret_cast<float *>( dest ) )[1] = m_y - m_dy;
    1084              :     }
    1085              :     else
    1086              :     {
    1087            0 :         ( reinterpret_cast<float *>( dest ) )[0] = m_x;
    1088            0 :         ( reinterpret_cast<float *>( dest ) )[1] = m_y;
    1089              :     }
    1090              : 
    1091            0 :     m_updated = false;
    1092              : 
    1093            0 :     return 0;
    1094              : }
    1095              : 
    1096            0 : inline int psfFit::reconfig()
    1097              : {
    1098            0 :     return 0;
    1099              : }
    1100              : 
    1101            0 : INDI_NEWCALLBACK_DEFN( psfFit, m_indiP_reset )( const pcf::IndiProperty &ipRecv )
    1102              : {
    1103            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_reset, ipRecv );
    1104              : 
    1105            0 :     if( ipRecv.find( "request" ) != true ) // this isn't valid
    1106              :     {
    1107            0 :         return -1;
    1108              :     }
    1109              : 
    1110            0 :     if( ipRecv["request"].getSwitchState() == pcf::IndiElement::On )
    1111              :     {
    1112            0 :         log<text_log>( "reset requested", logPrio::LOG_NOTICE );
    1113            0 :         shmimMonitorT::m_restart = true;
    1114              :     }
    1115              : 
    1116            0 :     return 0;
    1117              : }
    1118              : 
    1119            0 : INDI_NEWCALLBACK_DEFN( psfFit, m_indiP_statsTime )( const pcf::IndiProperty &ipRecv )
    1120              : {
    1121            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_statsTime, ipRecv );
    1122              : 
    1123              :     float target;
    1124              : 
    1125            0 :     if( indiTargetUpdate( m_indiP_statsTime, target, ipRecv, true ) < 0 )
    1126              :     {
    1127            0 :         log<software_error>( { __FILE__, __LINE__ } );
    1128            0 :         return -1;
    1129              :     }
    1130              : 
    1131            0 :     m_fitCircBuffMaxTime = target;
    1132              : 
    1133            0 :     shmimMonitorT::m_restart = true;
    1134              : 
    1135            0 :     log<text_log>( "set statsTime = " + std::to_string( m_fitCircBuffMaxTime ), logPrio::LOG_NOTICE );
    1136              : 
    1137            0 :     return 0;
    1138              : }
    1139              : 
    1140            0 : INDI_NEWCALLBACK_DEFN( psfFit, m_indiP_deltaPixThresh )( const pcf::IndiProperty &ipRecv )
    1141              : {
    1142            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_deltaPixThresh, ipRecv );
    1143              : 
    1144              :     float target;
    1145              : 
    1146            0 :     if( indiTargetUpdate( m_indiP_deltaPixThresh, target, ipRecv, true ) < 0 )
    1147              :     {
    1148            0 :         log<software_error>( { __FILE__, __LINE__ } );
    1149            0 :         return -1;
    1150              :     }
    1151              : 
    1152            0 :     m_deltaPixThresh = target;
    1153            0 :     updatesIfChanged<float>( m_indiP_deltaPixThresh, { "current", "target" }, { m_deltaPixThresh, m_deltaPixThresh } );
    1154            0 :     log<text_log>( "set deltaPixThresh = " + std::to_string( m_deltaPixThresh ), logPrio::LOG_NOTICE );
    1155            0 :     return 0;
    1156              : }
    1157              : 
    1158            0 : INDI_NEWCALLBACK_DEFN( psfFit, m_indiP_sigmaMaxThreshUp )( const pcf::IndiProperty &ipRecv )
    1159              : {
    1160            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_sigmaMaxThreshUp, ipRecv );
    1161              : 
    1162              :     float target;
    1163              : 
    1164            0 :     if( indiTargetUpdate( m_indiP_sigmaMaxThreshUp, target, ipRecv, true ) < 0 )
    1165              :     {
    1166            0 :         log<software_error>( { __FILE__, __LINE__ } );
    1167            0 :         return -1;
    1168              :     }
    1169              : 
    1170            0 :     m_sigmaMaxThreshUp = target;
    1171            0 :     updatesIfChanged<float>(
    1172            0 :         m_indiP_sigmaMaxThreshUp, { "current", "target" }, { m_sigmaMaxThreshUp, m_sigmaMaxThreshUp } );
    1173              : 
    1174            0 :     log<text_log>( "set sigmaMaxThreshUp = " + std::to_string( m_sigmaMaxThreshUp ), logPrio::LOG_NOTICE );
    1175            0 :     return 0;
    1176              : }
    1177              : 
    1178            0 : INDI_NEWCALLBACK_DEFN( psfFit, m_indiP_fractionMaxThreshDown )( const pcf::IndiProperty &ipRecv )
    1179              : {
    1180            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_fractionMaxThreshDown, ipRecv );
    1181              : 
    1182              :     float target;
    1183              : 
    1184            0 :     if( indiTargetUpdate( m_indiP_fractionMaxThreshDown, target, ipRecv, true ) < 0 )
    1185              :     {
    1186            0 :         log<software_error>( { __FILE__, __LINE__ } );
    1187            0 :         return -1;
    1188              :     }
    1189              : 
    1190            0 :     m_fractionMaxThreshDown = target;
    1191            0 :     updatesIfChanged<float>(
    1192            0 :         m_indiP_fractionMaxThreshDown, { "current", "target" }, { m_fractionMaxThreshDown, m_fractionMaxThreshDown } );
    1193              : 
    1194            0 :     log<text_log>( "set fractionMaxThreshDown = " + std::to_string( m_fractionMaxThreshDown ), logPrio::LOG_NOTICE );
    1195            0 :     return 0;
    1196              : }
    1197              : 
    1198            0 : INDI_NEWCALLBACK_DEFN( psfFit, m_indiP_sigmaPixThresh )( const pcf::IndiProperty &ipRecv )
    1199              : {
    1200            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_sigmaPixThresh, ipRecv );
    1201              : 
    1202              :     float target;
    1203              : 
    1204            0 :     if( indiTargetUpdate( m_indiP_sigmaPixThresh, target, ipRecv, true ) < 0 )
    1205              :     {
    1206            0 :         log<software_error>( { __FILE__, __LINE__ } );
    1207            0 :         return -1;
    1208              :     }
    1209              : 
    1210            0 :     m_sigmaPixThresh = target;
    1211            0 :     updatesIfChanged<float>( m_indiP_sigmaPixThresh, { "current", "target" }, { m_sigmaPixThresh, m_sigmaPixThresh } );
    1212              : 
    1213            0 :     log<text_log>( "set fractionMaxThreshDown = " + std::to_string( m_sigmaPixThresh ), logPrio::LOG_NOTICE );
    1214            0 :     return 0;
    1215              : }
    1216              : 
    1217            0 : INDI_NEWCALLBACK_DEFN( psfFit, m_indiP_dx )( const pcf::IndiProperty &ipRecv )
    1218              : {
    1219            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_dx, ipRecv );
    1220              : 
    1221              :     float target;
    1222              : 
    1223            0 :     if( indiTargetUpdate( m_indiP_dx, target, ipRecv, true ) < 0 )
    1224              :     {
    1225            0 :         log<software_error>( { __FILE__, __LINE__ } );
    1226            0 :         return -1;
    1227              :     }
    1228              : 
    1229            0 :     m_dx = target;
    1230              : 
    1231            0 :     log<text_log>( "set dx = " + std::to_string( m_dx ), logPrio::LOG_NOTICE );
    1232            0 :     return 0;
    1233              : }
    1234              : 
    1235            0 : INDI_NEWCALLBACK_DEFN( psfFit, m_indiP_dy )( const pcf::IndiProperty &ipRecv )
    1236              : {
    1237            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_dy, ipRecv );
    1238              : 
    1239              :     float target;
    1240              : 
    1241            0 :     if( indiTargetUpdate( m_indiP_dy, target, ipRecv, true ) < 0 )
    1242              :     {
    1243            0 :         log<software_error>( { __FILE__, __LINE__ } );
    1244            0 :         return -1;
    1245              :     }
    1246              : 
    1247            0 :     m_dy = target;
    1248              : 
    1249            0 :     log<text_log>( "set dy = " + std::to_string( m_dy ), logPrio::LOG_NOTICE );
    1250            0 :     return 0;
    1251              : }
    1252              : 
    1253            0 : INDI_SETCALLBACK_DEFN( psfFit, m_indiP_fpsSource )( const pcf::IndiProperty &ipRecv )
    1254              : {
    1255            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_fpsSource, ipRecv );
    1256              : 
    1257            0 :     if( ipRecv.find( m_fpsElement ) != true ) // this isn't valid
    1258              :     {
    1259            0 :         return 0;
    1260              :     }
    1261              : 
    1262            0 :     std::lock_guard<std::mutex> guard( m_indiMutex );
    1263              : 
    1264            0 :     realT fps = ipRecv[m_fpsElement].get<float>();
    1265              : 
    1266            0 :     if( fabs( fps - m_fps ) > m_fpsTol )
    1267              :     {
    1268            0 :         m_fps = fps;
    1269              : 
    1270            0 :         shmimMonitorT::m_restart = true;
    1271            0 :         frameGrabberT::m_reconfig = true;
    1272              :     }
    1273              : 
    1274            0 :     return 0;
    1275            0 : }
    1276              : 
    1277            0 : INDI_SETCALLBACK_DEFN( psfFit, m_indiP_shutter )( const pcf::IndiProperty &ipRecv )
    1278              : {
    1279            0 :     INDI_VALIDATE_CALLBACK_PROPS( m_indiP_shutter, ipRecv );
    1280              : 
    1281            0 :     if( ipRecv.find( m_shutterElement ) != true ) // this isn't valid
    1282              :     {
    1283            0 :         return 0;
    1284              :     }
    1285              : 
    1286            0 :     std::lock_guard<std::mutex> guard( m_indiMutex );
    1287              : 
    1288              :     bool shutter;
    1289            0 :     if( ipRecv[m_shutterElement].getSwitchState() == pcf::IndiElement::On )
    1290              :     {
    1291            0 :         shutter = true;
    1292              :     }
    1293              :     else
    1294              :     {
    1295            0 :         shutter = false;
    1296              :     }
    1297              : 
    1298            0 :     if( shutter != m_shutter )
    1299              :     {
    1300            0 :         m_shutter = shutter;
    1301              : 
    1302            0 :         shmimMonitorT::m_restart = true;
    1303              :     }
    1304              : 
    1305            0 :     return 0;
    1306            0 : }
    1307              : 
    1308            0 : inline int psfFit::checkRecordTimes()
    1309              : {
    1310            0 :     return telemeterT::checkRecordTimes( telem_fgtimings() );
    1311              : }
    1312              : 
    1313            0 : inline int psfFit::recordTelem( const telem_fgtimings * )
    1314              : {
    1315            0 :     return recordFGTimings( true );
    1316              : }
    1317              : 
    1318              : } // namespace app
    1319              : } // namespace MagAOX
    1320              : 
    1321              : #endif // psfFit_hpp
        

Generated by: LCOV version 2.0-1