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

            Line data    Source code
       1              : /** \file pupilFit.hpp
       2              :   * \brief The MagAO-X Pyramid Pupil Fitter application header
       3              :   *
       4              :   * \ingroup pupilFit_files
       5              :   */
       6              : 
       7              : #ifndef pupilFit_hpp
       8              : #define pupilFit_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              : #include "pupilFitter.hpp"
      14              : 
      15              : /** \defgroup pupilFit
      16              :   * \brief The MagAO-X pyramid pupil fitter.
      17              :   *
      18              :   * <a href="../handbook/operating/software/apps/pupilFit.html">Application Documentation</a>
      19              :   *
      20              :   * \ingroup apps
      21              :   *
      22              :   */
      23              : 
      24              : /** \defgroup pupilFit_files
      25              :   * \ingroup pupilFit
      26              :   */
      27              : 
      28              : namespace MagAOX
      29              : {
      30              : namespace app
      31              : {
      32              : 
      33              : struct refShmimT
      34              : {
      35            0 :    static std::string configSection()
      36              :    {
      37            0 :       return "refShmim";
      38              :    };
      39              : 
      40            0 :    static std::string indiPrefix()
      41              :    {
      42            0 :       return "ref";
      43              :    };
      44              : };
      45              : 
      46              : #define USEDEFSET (0)
      47              : #define USEREFIM (1)
      48              : #define USEUSERSET (2)
      49              : 
      50              : /// The MagAO-X Pyramid Pupil Fitter
      51              : /**
      52              :   * \ingroup pupilFit
      53              :   */
      54              : class pupilFit : public MagAOXApp<true>, public dev::shmimMonitor<pupilFit>, public dev::shmimMonitor<pupilFit,refShmimT>, public dev::frameGrabber<pupilFit>, public dev::telemeter<pupilFit>
      55              : {
      56              :    //Give the test harness access.
      57              :    friend class pupilFit_test;
      58              : 
      59              :    friend class dev::shmimMonitor<pupilFit>;
      60              :    friend class dev::shmimMonitor<pupilFit,refShmimT>;
      61              :    friend class dev::frameGrabber<pupilFit>;
      62              : 
      63              :    friend class dev::telemeter<pupilFit>;
      64              : 
      65              : public:
      66              :    //The base shmimMonitor type
      67              :    typedef dev::shmimMonitor<pupilFit> shmimMonitorT;
      68              : 
      69              :    typedef dev::shmimMonitor<pupilFit,refShmimT> refShmimMonitorT;
      70              : 
      71              :    //The base frameGrabber type
      72              :    typedef dev::frameGrabber<pupilFit> frameGrabberT;
      73              : 
      74              :    //The base telemeter type
      75              :    typedef dev::telemeter<pupilFit> telemeterT;
      76              : 
      77              :    ///Floating point type in which to do all calculations.
      78              :    typedef float realT;
      79              : 
      80              :    /** \name app::dev Configurations
      81              :      *@{
      82              :      */
      83              : 
      84              :    static constexpr bool c_frameGrabber_flippable = false; ///< app:dev config to tell framegrabber these images can not be flipped
      85              : 
      86              :    ///@}
      87              : 
      88              : protected:
      89              : 
      90              :    /** \name Configurable Parameters
      91              :      *@{
      92              :      */
      93              : 
      94              :    std::string m_threshShmimName {"camwfs_thresh"}; ///<The name of the image stream for the thresholded images.  Default is camwfs_thresh.
      95              :    std::string m_edgeShmimName {"camwfs_edge"}; ///<The name of the image stream for the edge images.  Default is camwfs_edge.
      96              : 
      97              :    float m_threshold {0.5};
      98              : 
      99              :    int m_numPupils {4}; ///< The number of pupils.  Default is 4.  3 is also supported.
     100              :    ///@}
     101              : 
     102              :    mx::improc::eigenImage<float> m_refIm;
     103              :    mx::improc::eigenImage<float> m_fitIm;
     104              :    mx::improc::eigenImage<float> m_edgeIm;
     105              : 
     106              :    pupilFitter<realT> m_fitter;
     107              : 
     108              :    IMAGE m_threshShmim;
     109              :    bool m_threshShmimConnected {false};
     110              : 
     111              :    IMAGE m_edgeShmim;
     112              :    bool m_edgeShmimConnected {false};
     113              : 
     114              :    float m_defSetx1 {29.5};
     115              :    float m_defSety1 {29.5};
     116              :    float m_defSetD1 {56.0};
     117              : 
     118              :    float m_defSetx2 {89.5};
     119              :    float m_defSety2 {29.5};
     120              :    float m_defSetD2 {56.0};
     121              : 
     122              :    float m_defSetx3 {29.5};
     123              :    float m_defSety3 {89.5};
     124              :    float m_defSetD3 {56.0};
     125              : 
     126              :    float m_defSetx4 {89.5};
     127              :    float m_defSety4 {89.5};
     128              :    float m_defSetD4 {56.0};
     129              : 
     130              :    float m_userSetx1 {29.5};
     131              :    float m_userSety1 {29.5};
     132              :    float m_userSetD1 {56.0};
     133              : 
     134              :    float m_userSetx2 {89.5};
     135              :    float m_userSety2 {29.5};
     136              :    float m_userSetD2 {56.0};
     137              : 
     138              :    float m_userSetx3 {29.5};
     139              :    float m_userSety3 {89.5};
     140              :    float m_userSetD3 {56.0};
     141              : 
     142              :    float m_userSetx4 {89.5};
     143              :    float m_userSety4 {89.5};
     144              :    float m_userSetD4 {56.0};
     145              : 
     146              :    int m_setPointSource {USEDEFSET};
     147              : 
     148              :    bool m_refUpdated {false}; ///< Flag set if the online reference update is used.
     149              : 
     150              :    float m_setx1 {29.5};
     151              :    float m_sety1 {29.5};
     152              :    float m_setD1 {56.0};
     153              : 
     154              :    float m_setx2 {89.5};
     155              :    float m_sety2 {29.5};
     156              :    float m_setD2 {56.0};
     157              : 
     158              :    float m_setx3 {29.5};
     159              :    float m_sety3 {89.5};
     160              :    float m_setD3 {56.0};
     161              : 
     162              :    float m_setx4 {89.5};
     163              :    float m_sety4 {89.5};
     164              :    float m_setD4 {56.0};
     165              : 
     166              :    float m_avg_dx {0};
     167              :    float m_avg_dy {0};
     168              : 
     169              :    bool m_averaging {false};
     170              :    size_t m_navg {0};
     171              : 
     172              :    float m_avgx1_accum {0};
     173              :    float m_avgx1sq_accum {0};
     174              : 
     175              :    float m_avgy1_accum {0};
     176              :    float m_avgy1sq_accum {0};
     177              : 
     178              :    float m_avgD1_accum {0};
     179              :    float m_avgD1sq_accum {0};
     180              : 
     181              :    float m_avgmed1_accum {0};
     182              :    float m_avgmed1sq_accum {0};
     183              : 
     184              :    float m_avgx1 {0};
     185              :    float m_varx1 {0};
     186              : 
     187              :    float m_avgy1 {0};
     188              :    float m_vary1 {0};
     189              : 
     190              :    float m_avgD1 {0};
     191              :    float m_varD1 {0};
     192              : 
     193              :    float m_avgmed1 {0};
     194              :    float m_varmed1 {0};
     195              : 
     196              :    float m_avgx2_accum {0};
     197              :    float m_avgx2sq_accum {0};
     198              : 
     199              :    float m_avgy2_accum {0};
     200              :    float m_avgy2sq_accum {0};
     201              : 
     202              :    float m_avgD2_accum {0};
     203              :    float m_avgD2sq_accum {0};
     204              : 
     205              :    float m_avgmed2_accum {0};
     206              :    float m_avgmed2sq_accum {0};
     207              : 
     208              :    float m_avgx2 {0};
     209              :    float m_varx2 {0};
     210              : 
     211              :    float m_avgy2 {0};
     212              :    float m_vary2 {0};
     213              : 
     214              :    float m_avgD2 {0};
     215              :    float m_varD2 {0};
     216              : 
     217              :    float m_avgmed2 {0};
     218              :    float m_varmed2 {0};
     219              : 
     220              :    float m_avgx3_accum {0};
     221              :    float m_avgx3sq_accum {0};
     222              : 
     223              :    float m_avgy3_accum {0};
     224              :    float m_avgy3sq_accum {0};
     225              : 
     226              :    float m_avgD3_accum {0};
     227              :    float m_avgD3sq_accum {0};
     228              : 
     229              :    float m_avgmed3_accum {0};
     230              :    float m_avgmed3sq_accum {0};
     231              : 
     232              :    float m_avgx3 {0};
     233              :    float m_varx3 {0};
     234              : 
     235              :    float m_avgy3 {0};
     236              :    float m_vary3 {0};
     237              : 
     238              :    float m_avgD3 {0};
     239              :    float m_varD3 {0};
     240              : 
     241              :    float m_avgmed3 {0};
     242              :    float m_varmed3 {0};
     243              : 
     244              :    float m_avgx4_accum {0};
     245              :    float m_avgx4sq_accum {0};
     246              : 
     247              :    float m_avgy4_accum {0};
     248              :    float m_avgy4sq_accum {0};
     249              : 
     250              :    float m_avgD4_accum {0};
     251              :    float m_avgD4sq_accum {0};
     252              : 
     253              :    float m_avgmed4_accum {0};
     254              :    float m_avgmed4sq_accum {0};
     255              : 
     256              :    float m_avgx4 {0};
     257              :    float m_varx4 {0};
     258              : 
     259              :    float m_avgy4 {0};
     260              :    float m_vary4 {0};
     261              : 
     262              :    float m_avgD4 {0};
     263              :    float m_varD4 {0};
     264              : 
     265              :    float m_avgmed4 {0};
     266              :    float m_varmed4 {0};
     267              : 
     268              :    float m_avgxAll_accum {0};
     269              :    float m_avgxAllsq_accum {0};
     270              : 
     271              :    float m_avgyAll_accum {0};
     272              :    float m_avgyAllsq_accum {0};
     273              : 
     274              :    float m_avgDAll_accum {0};
     275              :    float m_avgDAllsq_accum {0};
     276              : 
     277              :    float m_avgmedAll_accum {0};
     278              :    float m_avgmedAllsq_accum {0};
     279              : 
     280              :    float m_avgxAll {0};
     281              :    float m_varxAll {0};
     282              : 
     283              :    float m_avgyAll {0};
     284              :    float m_varyAll {0};
     285              : 
     286              :    float m_avgDAll {0};
     287              :    float m_varDAll {0};
     288              : 
     289              :    float m_avgmedAll {0};
     290              :    float m_varmedAll {0};
     291              : 
     292              : public:
     293              :    /// Default c'tor.
     294              :    pupilFit();
     295              : 
     296              :    /// D'tor, declared and defined for noexcept.
     297              :    ~pupilFit() noexcept;
     298              : 
     299              :    virtual void setupConfig();
     300              : 
     301              :    /// Implementation of loadConfig logic, separated for testing.
     302              :    /** This is called by loadConfig().
     303              :      */
     304              :    int loadConfigImpl( mx::app::appConfigurator & _config /**< [in] an application configuration from which to load values*/);
     305              : 
     306              :    virtual void loadConfig();
     307              : 
     308              :    /// Startup function
     309              :    /**
     310              :      *
     311              :      */
     312              :    virtual int appStartup();
     313              : 
     314              :    /// Implementation of the FSM for pupilFit.
     315              :    /**
     316              :      * \returns 0 on no critical error
     317              :      * \returns -1 on an error requiring shutdown
     318              :      */
     319              :    virtual int appLogic();
     320              : 
     321              :    /// Shutdown the app.
     322              :    /**
     323              :      *
     324              :      */
     325              :    virtual int appShutdown();
     326              : 
     327              :    // shmimMonitor interface:
     328              :    int allocate( const dev::shmimT &);
     329              : 
     330              :    int processImage( void* curr_src,
     331              :                      const dev::shmimT &
     332              :                     );
     333              : 
     334              :    // shmimMonitor interface for referenc:
     335              :    int allocate( const refShmimT &);
     336              : 
     337              :    int processImage( void* curr_src,
     338              :                      const refShmimT &
     339              :                    );
     340              : 
     341              : protected:
     342              : 
     343              :    bool m_updated {false}; //tells the f.g. that there is an actual image, not just a sem timeout
     344              : 
     345              :    sem_t m_smSemaphore {0}; ///< Semaphore used to synchronize the fg thread and the sm thread.
     346              : 
     347              : public:
     348              : 
     349              :    /** \name dev::frameGrabber interface
     350              :      *
     351              :      * @{
     352              :      */
     353              : 
     354              :    /// Implementation of the framegrabber configureAcquisition interface
     355              :    /**
     356              :      * \returns 0 on success
     357              :      * \returns -1 on error
     358              :      */
     359              :    int configureAcquisition();
     360              : 
     361              :    /// Implementation of the framegrabber fps interface
     362              :    /**
     363              :      * \todo this needs to infer the stream fps and return it
     364              :      */
     365            0 :    float fps()
     366              :    {
     367            0 :       return 1.0;
     368              :    }
     369              : 
     370              :    /// Implementation of the framegrabber startAcquisition interface
     371              :    /**
     372              :      * \returns 0 on success
     373              :      * \returns -1 on error
     374              :      */
     375              :    int startAcquisition();
     376              : 
     377              :    /// Implementation of the framegrabber acquireAndCheckValid interface
     378              :    /**
     379              :      * \returns 0 on success
     380              :      * \returns -1 on error
     381              :      */
     382              :    int acquireAndCheckValid();
     383              : 
     384              :    /// Implementation of the framegrabber loadImageIntoStream interface
     385              :    /**
     386              :      * \returns 0 on success
     387              :      * \returns -1 on error
     388              :      */
     389              :    int loadImageIntoStream( void * dest  /**< [in] */);
     390              : 
     391              :    /// Implementation of the framegrabber reconfig interface
     392              :    /**
     393              :      * \returns 0 on success
     394              :      * \returns -1 on error
     395              :      */
     396              :    int reconfig();
     397              : 
     398              :    ///@}
     399              : 
     400              : protected:
     401              : 
     402              :    /** \name INDI
     403              :      * @{
     404              :      */
     405              : 
     406              :    pcf::IndiProperty m_indiP_thresh;
     407              : 
     408            0 :    INDI_NEWCALLBACK_DECL(pupilFit, m_indiP_thresh);
     409              : 
     410              :    pcf::IndiProperty m_indiP_averaging;
     411            0 :    INDI_NEWCALLBACK_DECL(pupilFit, m_indiP_averaging);
     412              : 
     413              :    pcf::IndiProperty m_indiP_numPupils;
     414              : 
     415              :    pcf::IndiProperty m_indiP_quad1;
     416              :    pcf::IndiProperty m_indiP_quad2;
     417              :    pcf::IndiProperty m_indiP_quad3;
     418              :    pcf::IndiProperty m_indiP_quad4;
     419              : 
     420              :    pcf::IndiProperty m_indiP_avg;
     421              : 
     422              :    pcf::IndiProperty m_indiP_reload;
     423            0 :    INDI_NEWCALLBACK_DECL(pupilFit, m_indiP_reload);
     424              : 
     425              :    pcf::IndiProperty m_indiP_update;
     426            0 :    INDI_NEWCALLBACK_DECL(pupilFit, m_indiP_update);
     427              : 
     428              :    pcf::IndiProperty m_indiP_refmode;
     429            0 :    INDI_NEWCALLBACK_DECL(pupilFit, m_indiP_refmode);
     430              : 
     431              :    ///@}
     432              : 
     433              :    /** \name Telemeter Interface
     434              :      *
     435              :      * @{
     436              :      */
     437              :    int checkRecordTimes();
     438              : 
     439              :    int recordTelem( const telem_fgtimings * );
     440              : 
     441              :    ///@}
     442              : };
     443              : 
     444              : inline
     445              : pupilFit::pupilFit() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
     446              : {
     447              :    refShmimMonitorT::m_getExistingFirst = true;
     448              :    return;
     449              : }
     450              : 
     451              : inline
     452            0 : pupilFit::~pupilFit() noexcept
     453              : {
     454            0 :    if(m_threshShmimConnected)
     455              :    {
     456            0 :       ImageStreamIO_destroyIm( &m_threshShmim );
     457              :    }
     458              : 
     459            0 :    if(m_edgeShmimConnected)
     460              :    {
     461            0 :       ImageStreamIO_destroyIm( &m_edgeShmim );
     462              :    }
     463            0 : }
     464              : 
     465              : inline
     466            0 : void pupilFit::setupConfig()
     467              : {
     468            0 :    shmimMonitorT::setupConfig(config);
     469            0 :    refShmimMonitorT::setupConfig(config);
     470            0 :    frameGrabberT::setupConfig(config);
     471            0 :    telemeterT::setupConfig(config);
     472              : 
     473            0 :    config.add("shmimMonitor.shmimName", "", "shmimMonitor.shmimName", argType::Required, "shmimMonitor", "shmimName", false, "string", "The name of the ImageStreamIO shared memory image. Will be used as /tmp/<shmimName>.im.shm. Default is camwfs_avg");
     474              : 
     475            0 :    config.add("fit.threshold", "", "fit.threshold", argType::Required, "fit", "threshold", false, "float", "The pupil finding threshold. 0 < threshold < 1");
     476            0 :    config.add("fit.threshShmimName", "", "fit.threshShmimName", argType::Required, "fit", "threshShmimName", false, "float", "The name of the image stream for the thresholded images.  Default is camwfs_thresh.");
     477            0 :    config.add("fit.edgeShmimName", "", "fit.edgeShmimName", argType::Required, "fit", "edgeShmimName", false, "float", "The name of the image stream for the edge images.  Default is camwfs_edge.");
     478              : 
     479            0 :    config.add("fit.numPupils", "", "fit.numPupils", argType::Required, "fit", "numPupils", false, "int", "The number of pupils.  Default is 4.  3 is also supported.");
     480            0 :    config.add("fit.pupMedIndex", "", "fit.pupMedIndex", argType::Required, "fit", "pupMedIndex", false, "float", "The index of the pupil median in a sorted quadrant.");
     481              : 
     482            0 :    config.add("cal.setx1", "", "cal.setx1", argType::Required, "cal", "setx1", false, "float", "The x set point for quad 1 (LL).");
     483            0 :    config.add("cal.sety1", "", "cal.sety1", argType::Required, "cal", "sety1", false, "float", "The y set point for quad 1 (LL).");
     484            0 :    config.add("cal.setD1", "", "cal.setD1", argType::Required, "cal", "setD1", false, "float", "The D set point for quad 1 (LL).");
     485              : 
     486            0 :    config.add("cal.setx2", "", "cal.setx2", argType::Required, "cal", "setx2", false, "float", "The x set point for quad 2 (LL).");
     487            0 :    config.add("cal.sety2", "", "cal.sety2", argType::Required, "cal", "sety2", false, "float", "The y set point for quad 2 (LL).");
     488            0 :    config.add("cal.setD2", "", "cal.setD2", argType::Required, "cal", "setD2", false, "float", "The D set point for quad 2 (LL).");
     489              : 
     490            0 :    config.add("cal.setx3", "", "cal.setx3", argType::Required, "cal", "setx3", false, "float", "The x set point for quad 3 (LL).");
     491            0 :    config.add("cal.sety3", "", "cal.sety3", argType::Required, "cal", "sety3", false, "float", "The y set point for quad 3 (LL).");
     492            0 :    config.add("cal.setD3", "", "cal.setD3", argType::Required, "cal", "setD3", false, "float", "The D set point for quad 3 (LL).");
     493              : 
     494            0 :    config.add("cal.setx4", "", "cal.setx4", argType::Required, "cal", "setx4", false, "float", "The x set point for quad 4 (LL).");
     495            0 :    config.add("cal.sety4", "", "cal.sety4", argType::Required, "cal", "sety4", false, "float", "The y set point for quad 4 (LL).");
     496            0 :    config.add("cal.setD4", "", "cal.setD4", argType::Required, "cal", "setD4", false, "float", "The D set point for quad 4 (LL).");
     497            0 : }
     498              : 
     499              : 
     500              : inline
     501            0 : int pupilFit::loadConfigImpl( mx::app::appConfigurator & _config )
     502              : {
     503            0 :    shmimMonitorT::m_shmimName = "camwfs_avg";
     504            0 :    shmimMonitorT::loadConfig(_config);
     505            0 :    refShmimMonitorT::loadConfig(_config);
     506            0 :    if(refShmimMonitorT::m_shmimName != "") m_setPointSource = USEREFIM;
     507              : 
     508            0 :    frameGrabberT::loadConfig(_config);
     509            0 :    telemeterT::loadConfig(_config);
     510              : 
     511            0 :    _config(m_threshold, "fit.threshold");
     512            0 :    _config(m_threshShmimName, "fit.threshShmimName");
     513            0 :    _config(m_edgeShmimName, "fit.edgeShmimName");
     514            0 :    _config(m_numPupils, "fit.numPupils");
     515            0 :    _config(m_fitter.m_pupMedIndex, "fit.pupMedIndex");
     516              : 
     517            0 :    _config(m_defSetx1, "cal.setx1");
     518            0 :    _config(m_defSety1, "cal.sety1");
     519            0 :    _config(m_defSetD1, "cal.setD1");
     520              : 
     521            0 :    _config(m_defSetx2, "cal.setx2");
     522            0 :    _config(m_defSety2, "cal.sety2");
     523            0 :    _config(m_defSetD2, "cal.setD2");
     524              : 
     525            0 :    _config(m_defSetx3, "cal.setx3");
     526            0 :    _config(m_defSety3, "cal.sety3");
     527            0 :    _config(m_defSetD3, "cal.setD3");
     528              : 
     529            0 :    _config(m_defSetx4, "cal.setx4");
     530            0 :    _config(m_defSety4, "cal.sety4");
     531            0 :    _config(m_defSetD4, "cal.setD4");
     532              : 
     533              : 
     534            0 :    return 0;
     535              : }
     536              : 
     537              : inline
     538            0 : void pupilFit::loadConfig()
     539              : {
     540            0 :    loadConfigImpl(config);
     541            0 : }
     542              : 
     543              : inline
     544            0 : int pupilFit::appStartup()
     545              : {
     546            0 :    if(shmimMonitorT::appStartup() < 0)
     547              :    {
     548            0 :       return log<software_error,-1>({__FILE__, __LINE__});
     549              :    }
     550              : 
     551            0 :    if(refShmimMonitorT::appStartup() < 0)
     552              :    {
     553            0 :       return log<software_error,-1>({__FILE__, __LINE__});
     554              :    }
     555              : 
     556            0 :    if(sem_init(&m_smSemaphore, 0,0) < 0)
     557              :    {
     558            0 :       log<software_critical>({__FILE__, __LINE__, errno,0, "Initializing S.M. semaphore"});
     559            0 :       return -1;
     560              :    }
     561              : 
     562            0 :    if(frameGrabberT::appStartup() < 0)
     563              :    {
     564            0 :       return log<software_error,-1>({__FILE__, __LINE__});
     565              :    }
     566              : 
     567            0 :    if(telemeterT::appStartup() < 0)
     568              :    {
     569            0 :       return log<software_error,-1>({__FILE__, __LINE__});
     570              :    }
     571              : 
     572            0 :    createStandardIndiNumber<float>( m_indiP_thresh, "threshold", 0, 1 ,0, "%0.2f", "Threshold");
     573            0 :    m_indiP_thresh["current"].set(m_threshold);
     574            0 :    m_indiP_thresh["target"].set(m_threshold);
     575            0 :    registerIndiPropertyNew(m_indiP_thresh, INDI_NEWCALLBACK(m_indiP_thresh));
     576              : 
     577            0 :    createStandardIndiToggleSw( m_indiP_averaging, "averaging", "Start/Stop Averaging");
     578            0 :    m_indiP_averaging["toggle"].set(pcf::IndiElement::Off);
     579            0 :    if( registerIndiPropertyNew( m_indiP_averaging, INDI_NEWCALLBACK(m_indiP_averaging)) < 0)
     580              :    {
     581            0 :       log<software_error>({__FILE__,__LINE__});
     582            0 :       return -1;
     583              :    }
     584              : 
     585            0 :    createROIndiNumber( m_indiP_numPupils, "numPupils", "Number of Pupils");
     586            0 :    indi::addNumberElement<int>( m_indiP_numPupils, "value", 3, 4, 1, "%d", "");
     587            0 :    m_indiP_numPupils["value"].set(m_numPupils);
     588            0 :    registerIndiPropertyReadOnly(m_indiP_numPupils);
     589              : 
     590            0 :    createROIndiNumber( m_indiP_quad1, "quadrant1", "Quadrant 1");
     591            0 :    indi::addNumberElement<float>( m_indiP_quad1, "x", 0, 59, 0, "%0.2f", "center x");
     592            0 :    indi::addNumberElement<float>( m_indiP_quad1, "dx", 0, 59, 0, "%0.2f", "delta-x");
     593            0 :    indi::addNumberElement<float>( m_indiP_quad1, "y", 0, 59, 0, "%0.2f", "center x");
     594            0 :    indi::addNumberElement<float>( m_indiP_quad1, "dy", 0, 59, 0, "%0.2f", "delta-y");
     595            0 :    indi::addNumberElement<float>( m_indiP_quad1, "D", 0, 59, 0, "%0.2f", "diameter");
     596            0 :    indi::addNumberElement<float>( m_indiP_quad1, "dD", 0, 59, 0, "%0.2f", "delta-D");
     597            0 :    indi::addNumberElement<float>( m_indiP_quad1, "med", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "flux");
     598            0 :    indi::addNumberElement<float>( m_indiP_quad1, "bg", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "background");
     599            0 :    indi::addNumberElement<float>( m_indiP_quad1, "set-x", 0, 59, 0, "%0.2f", "set pt. center x");
     600            0 :    m_indiP_quad1["set-x"] = m_setx1;
     601            0 :    indi::addNumberElement<float>( m_indiP_quad1, "set-y", 0, 59, 0, "%0.2f", "set pt. center x");
     602            0 :    m_indiP_quad1["set-y"] = m_sety1;
     603            0 :    indi::addNumberElement<float>( m_indiP_quad1, "set-D", 0, 59, 0, "%0.2f", "set pt. diameter");
     604            0 :    m_indiP_quad1["set-D"] = m_setD1;
     605              : 
     606            0 :    registerIndiPropertyReadOnly(m_indiP_quad1);
     607              : 
     608            0 :    createROIndiNumber( m_indiP_quad2, "quadrant2", "Quadrant 2");
     609            0 :    indi::addNumberElement<float>( m_indiP_quad2, "x", 0, 59, 0, "%0.2f", "center x");
     610            0 :    indi::addNumberElement<float>( m_indiP_quad2, "dx", 0, 59, 0, "%0.2f", "delta-x");
     611            0 :    indi::addNumberElement<float>( m_indiP_quad2, "y", 0, 59, 0, "%0.2f", "center y");
     612            0 :    indi::addNumberElement<float>( m_indiP_quad2, "dy", 0, 59, 0, "%0.2f", "delta-y");
     613            0 :    indi::addNumberElement<float>( m_indiP_quad2, "D", 0, 59, 0, "%0.2f", "diameter");
     614            0 :    indi::addNumberElement<float>( m_indiP_quad2, "dD", 0, 59, 0, "%0.2f", "delta-D");
     615            0 :    indi::addNumberElement<float>( m_indiP_quad2, "med", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "flux");
     616            0 :    indi::addNumberElement<float>( m_indiP_quad2, "bg", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "background");
     617            0 :    indi::addNumberElement<float>( m_indiP_quad2, "set-x", 0, 59, 0, "%0.2f", "set pt. center x");
     618            0 :    m_indiP_quad2["set-x"] = m_setx2;
     619            0 :    indi::addNumberElement<float>( m_indiP_quad2, "set-y", 0, 59, 0, "%0.2f", "set pt. center x");
     620            0 :    m_indiP_quad2["set-y"] = m_sety2;
     621            0 :    indi::addNumberElement<float>( m_indiP_quad2, "set-D", 0, 59, 0, "%0.2f", "set pt. diameter");
     622            0 :    m_indiP_quad2["set-D"] = m_setD2;
     623            0 :    registerIndiPropertyReadOnly(m_indiP_quad2);
     624              : 
     625            0 :    createROIndiNumber( m_indiP_quad3, "quadrant3", "Quadrant 3");
     626            0 :    indi::addNumberElement<float>( m_indiP_quad3, "x", 0, 59, 0, "%0.2f", "center x");
     627            0 :    indi::addNumberElement<float>( m_indiP_quad3, "dx", 0, 59, 0, "%0.2f", "delta-x");
     628            0 :    indi::addNumberElement<float>( m_indiP_quad3, "y", 0, 59, 0, "%0.2f", "center y");
     629            0 :    indi::addNumberElement<float>( m_indiP_quad3, "dy", 0, 59, 0, "%0.2f", "delta-y");
     630            0 :    indi::addNumberElement<float>( m_indiP_quad3, "D", 0, 59, 0, "%0.2f", "diameter");
     631            0 :    indi::addNumberElement<float>( m_indiP_quad3, "dD", 0, 59, 0, "%0.2f", "delta-D");
     632            0 :    indi::addNumberElement<float>( m_indiP_quad3, "med", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "flux");
     633            0 :    indi::addNumberElement<float>( m_indiP_quad3, "bg", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "background");
     634            0 :    indi::addNumberElement<float>( m_indiP_quad3, "set-x", 0, 59, 0, "%0.2f", "set pt. center x");
     635            0 :    m_indiP_quad3["set-x"] = m_setx3;
     636            0 :    indi::addNumberElement<float>( m_indiP_quad3, "set-y", 0, 59, 0, "%0.2f", "set pt. center x");
     637            0 :    m_indiP_quad3["set-y"] = m_sety3;
     638            0 :    indi::addNumberElement<float>( m_indiP_quad3, "set-D", 0, 59, 0, "%0.2f", "set pt. diameter");
     639            0 :    m_indiP_quad3["set-D"] = m_setD3;
     640            0 :    registerIndiPropertyReadOnly(m_indiP_quad3);
     641              : 
     642            0 :    if(m_numPupils != 3)
     643              :    {
     644            0 :       createROIndiNumber( m_indiP_quad4, "quadrant4", "Quadrant 4");
     645            0 :       indi::addNumberElement<float>( m_indiP_quad4, "x", 0, 59, 0, "%0.2f", "center x");
     646            0 :       indi::addNumberElement<float>( m_indiP_quad4, "dx", 0, 59, 0, "%0.2f", "delta-x");
     647            0 :       indi::addNumberElement<float>( m_indiP_quad4, "y", 0, 59, 0, "%0.2f", "center y");
     648            0 :       indi::addNumberElement<float>( m_indiP_quad4, "dy", 0, 59, 0, "%0.2f", "delta-y");
     649            0 :       indi::addNumberElement<float>( m_indiP_quad4, "D", 0, 59, 0, "%0.2f", "diameter");
     650            0 :       indi::addNumberElement<float>( m_indiP_quad4, "dD", 0, 59, 0, "%0.2f", "delta-D");
     651            0 :       indi::addNumberElement<float>( m_indiP_quad4, "med", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "flux");
     652            0 :       indi::addNumberElement<float>( m_indiP_quad4, "bg", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "background");
     653            0 :       indi::addNumberElement<float>( m_indiP_quad4, "set-x", 0, 59, 0, "%0.2f", "set pt. center x");
     654            0 :       m_indiP_quad4["set-x"] = m_setx4;
     655            0 :       indi::addNumberElement<float>( m_indiP_quad4, "set-y", 0, 59, 0, "%0.2f", "set pt. center x");
     656            0 :       m_indiP_quad4["set-y"] = m_sety4;
     657            0 :       indi::addNumberElement<float>( m_indiP_quad4, "set-D", 0, 59, 0, "%0.2f", "set pt. diameter");
     658            0 :       m_indiP_quad4["set-D"] = m_setD4;
     659            0 :       registerIndiPropertyReadOnly(m_indiP_quad4);
     660              :    }
     661              : 
     662            0 :    createROIndiNumber( m_indiP_avg, "average", "Average");
     663            0 :    indi::addNumberElement<float>( m_indiP_avg, "x", 0, 59, 0, "%0.2f", "center x");
     664            0 :    indi::addNumberElement<float>( m_indiP_avg, "dx", 0, 59, 0, "%0.2f", "delta-x");
     665            0 :    indi::addNumberElement<float>( m_indiP_avg, "y", 0, 59, 0, "%0.2f", "center y");
     666            0 :    indi::addNumberElement<float>( m_indiP_avg, "dy", 0, 59, 0, "%0.2f", "delta-y");
     667            0 :    indi::addNumberElement<float>( m_indiP_avg, "D", 0, 59, 0, "%0.2f", "diameter");
     668            0 :    indi::addNumberElement<float>( m_indiP_avg, "dD", 0, 59, 0, "%0.2f", "delta-D");
     669            0 :    registerIndiPropertyReadOnly(m_indiP_avg);
     670              : 
     671            0 :    createStandardIndiRequestSw( m_indiP_reload, "setpt_reload", "Reload Calibration");
     672            0 :    m_indiP_reload["request"].set(pcf::IndiElement::Off);
     673            0 :    if( registerIndiPropertyNew( m_indiP_reload, INDI_NEWCALLBACK(m_indiP_reload)) < 0)
     674              :    {
     675            0 :       log<software_error>({__FILE__,__LINE__});
     676            0 :       return -1;
     677              :    }
     678              : 
     679            0 :    createStandardIndiRequestSw( m_indiP_update, "setpt_current", "Set Reference");
     680            0 :    m_indiP_update["request"].set(pcf::IndiElement::Off);
     681            0 :    if( registerIndiPropertyNew( m_indiP_update, INDI_NEWCALLBACK(m_indiP_update)) < 0)
     682              :    {
     683            0 :       log<software_error>({__FILE__,__LINE__});
     684            0 :       return -1;
     685              :    }
     686              : 
     687            0 :    createStandardIndiSelectionSw( m_indiP_refmode, "setpt_mode", {"default", "refim", "user"}, "Reference Mode");
     688            0 :    if(m_setPointSource == USEREFIM)
     689              :    {
     690            0 :       m_indiP_refmode["default"].set(pcf::IndiElement::Off);
     691            0 :       m_indiP_refmode["refim"].set(pcf::IndiElement::On);
     692            0 :       m_indiP_refmode["user"].set(pcf::IndiElement::Off);
     693              :    }
     694            0 :    if(m_setPointSource == USEUSERSET)
     695              :    {
     696            0 :       m_indiP_refmode["default"].set(pcf::IndiElement::Off);
     697            0 :       m_indiP_refmode["refim"].set(pcf::IndiElement::Off);
     698            0 :       m_indiP_refmode["user"].set(pcf::IndiElement::On);
     699              :    }
     700              :    else
     701              :    {
     702            0 :       m_indiP_refmode["default"].set(pcf::IndiElement::On);
     703            0 :       m_indiP_refmode["refim"].set(pcf::IndiElement::Off);
     704            0 :       m_indiP_refmode["user"].set(pcf::IndiElement::Off);
     705              :    }
     706              : 
     707            0 :    if( registerIndiPropertyNew( m_indiP_refmode, INDI_NEWCALLBACK(m_indiP_refmode)) < 0)
     708              :    {
     709            0 :       log<software_error>({__FILE__,__LINE__});
     710            0 :       return -1;
     711              :    }
     712              : 
     713            0 :    state(stateCodes::OPERATING);
     714              : 
     715            0 :    return 0;
     716              : }
     717              : 
     718              : inline
     719            0 : int pupilFit::appLogic()
     720              : {
     721            0 :    if( shmimMonitorT::appLogic() < 0)
     722              :    {
     723            0 :       return log<software_error,-1>({__FILE__,__LINE__});
     724              :    }
     725              : 
     726            0 :    if( refShmimMonitorT::appLogic() < 0)
     727              :    {
     728            0 :       return log<software_error,-1>({__FILE__,__LINE__});
     729              :    }
     730              : 
     731            0 :    if( frameGrabberT::appLogic() < 0)
     732              :    {
     733            0 :       return log<software_error,-1>({__FILE__,__LINE__});
     734              :    }
     735              : 
     736            0 :    if( telemeterT::appLogic() < 0)
     737              :    {
     738            0 :       return log<software_error,-1>({__FILE__,__LINE__});
     739              :    }
     740              : 
     741            0 :    std::lock_guard<std::mutex> guard(m_indiMutex);
     742            0 :    updateIfChanged(m_indiP_thresh, "current", m_threshold, INDI_IDLE);
     743            0 :    updateIfChanged(m_indiP_thresh, "target", m_threshold, INDI_IDLE);
     744              : 
     745            0 :    if(m_setPointSource == USEREFIM)
     746              :    {
     747            0 :       updateSwitchIfChanged(m_indiP_refmode, "default", pcf::IndiElement::Off);
     748            0 :       updateSwitchIfChanged(m_indiP_refmode, "refim", pcf::IndiElement::On);
     749            0 :       updateSwitchIfChanged(m_indiP_refmode, "user", pcf::IndiElement::Off);
     750              :    }
     751            0 :    else if(m_setPointSource == USEUSERSET)
     752              :    {
     753            0 :       updateSwitchIfChanged(m_indiP_refmode, "default", pcf::IndiElement::Off);
     754            0 :       updateSwitchIfChanged(m_indiP_refmode, "refim", pcf::IndiElement::Off);
     755            0 :       updateSwitchIfChanged(m_indiP_refmode, "user", pcf::IndiElement::On);
     756              :    }
     757              :    else
     758              :    {
     759            0 :       updateSwitchIfChanged(m_indiP_refmode, "default", pcf::IndiElement::On);
     760            0 :       updateSwitchIfChanged(m_indiP_refmode, "refim", pcf::IndiElement::Off);
     761            0 :       updateSwitchIfChanged(m_indiP_refmode, "user", pcf::IndiElement::Off);
     762              :    }
     763              : 
     764            0 :    shmimMonitorT::updateINDI();
     765            0 :    refShmimMonitorT::updateINDI();
     766              : 
     767            0 :    if(frameGrabberT::updateINDI() < 0)
     768              :    {
     769            0 :       log<software_error>({__FILE__, __LINE__});
     770              :    }
     771              : 
     772            0 :    return 0;
     773            0 : }
     774              : 
     775              : inline
     776            0 : int pupilFit::appShutdown()
     777              : {
     778            0 :    shmimMonitorT::appShutdown();
     779            0 :    refShmimMonitorT::appShutdown();
     780            0 :    frameGrabberT::appShutdown();
     781            0 :    telemeterT::appShutdown();
     782              : 
     783            0 :    return 0;
     784              : }
     785              : 
     786              : inline
     787            0 : int pupilFit::allocate(const dev::shmimT & dummy)
     788              : {
     789              :    static_cast<void>(dummy);
     790              : 
     791            0 :    std::lock_guard<std::mutex> guard(m_indiMutex);
     792              : 
     793            0 :    m_fitIm.resize(shmimMonitorT::m_width, shmimMonitorT::m_height);
     794            0 :    m_edgeIm.resize(shmimMonitorT::m_width, shmimMonitorT::m_height);
     795              : 
     796            0 :    m_fitter.m_numPupils = m_numPupils;
     797            0 :    m_fitter.setSize(0.5*shmimMonitorT::m_width, 0.5*shmimMonitorT::m_height);
     798            0 :    m_fitter.m_thresh = m_threshold;
     799              : 
     800            0 :    if(m_setPointSource == USEREFIM && m_refIm.rows() == shmimMonitorT::m_width && m_refIm.cols() == shmimMonitorT::m_height)
     801              :    {
     802            0 :       mx::improc::eigenImage<float> refim, refedge;
     803            0 :       refim = m_refIm; //cuz it's modified by fitter.
     804            0 :       if(m_fitter.fit(refim, refedge) < 0)
     805              :       {
     806            0 :          return log<software_error, -1>({__FILE__, __LINE__, "error from fitter for reference"});
     807              :       }
     808              : 
     809            0 :       m_setx1 = m_fitter.m_avgx[0];
     810            0 :       m_sety1 = m_fitter.m_avgy[0];
     811            0 :       m_setD1 = 2*m_fitter.m_avgr[0];
     812              : 
     813            0 :       m_setx2 = m_fitter.m_avgx[1];
     814            0 :       m_sety2 = m_fitter.m_avgy[1];
     815            0 :       m_setD2 = 2*m_fitter.m_avgr[1];
     816              : 
     817            0 :       m_setx3 = m_fitter.m_avgx[2];
     818            0 :       m_sety3 = m_fitter.m_avgy[2];
     819            0 :       m_setD3 = 2*m_fitter.m_avgr[2];
     820              : 
     821            0 :       m_setx4 = m_fitter.m_avgx[3];
     822            0 :       m_sety4 = m_fitter.m_avgy[3];
     823            0 :       m_setD4 = 2*m_fitter.m_avgr[3];
     824              : 
     825            0 :       log<text_log>("Fit to reference image: ");
     826            0 :       log<text_log>("Quad 1 set points: " + std::to_string(m_setx1) + " " +  std::to_string(m_sety1) + " " + std::to_string(m_setD1));
     827            0 :       log<text_log>("Quad 2 set points: " + std::to_string(m_setx2) + " " +  std::to_string(m_sety2) + " " + std::to_string(m_setD2));
     828            0 :       log<text_log>("Quad 3 set points: " + std::to_string(m_setx3) + " " +  std::to_string(m_sety3) + " " + std::to_string(m_setD3));
     829            0 :       log<text_log>("Quad 4 set points: " + std::to_string(m_setx4) + " " +  std::to_string(m_sety4) + " " + std::to_string(m_setD4));
     830            0 :    }
     831              :    else
     832              :    {
     833            0 :       if(m_setPointSource == USEREFIM && (m_refIm.rows() != shmimMonitorT::m_width || m_refIm.cols() != shmimMonitorT::m_height))
     834              :       {
     835            0 :          if(m_refIm.rows()!=0 || m_refIm.cols() != 0) //only complain if the ref image has been loaded
     836              :          {
     837            0 :             log<text_log>("Reference image size does not match", logPrio::LOG_ERROR);
     838              :          }
     839              :       }
     840              : 
     841            0 :       if(m_setPointSource == USEUSERSET)
     842              :       {
     843            0 :          m_setx1 = m_userSetx1;
     844            0 :          m_sety1 = m_userSety1;
     845            0 :          m_setD1 = m_userSetD1;
     846              : 
     847            0 :          m_setx2 = m_userSetx2;
     848            0 :          m_sety2 = m_userSety2;
     849            0 :          m_setD2 = m_userSetD2;
     850              : 
     851            0 :          m_setx3 = m_userSetx3;
     852            0 :          m_sety3 = m_userSety3;
     853            0 :          m_setD3 = m_userSetD3;
     854              : 
     855            0 :          if(m_numPupils == 4)
     856              :          {
     857            0 :             m_setx4 = m_userSetx4;
     858            0 :             m_sety4 = m_userSety4;
     859            0 :             m_setD4 = m_userSetD4;
     860              :          }
     861            0 :          log<text_log>("Using user set-points");
     862              : 
     863              :       }
     864              :       else
     865              :       {
     866            0 :          m_setx1 = m_defSetx1;
     867            0 :          m_sety1 = m_defSety1;
     868            0 :          m_setD1 = m_defSetD1;
     869              : 
     870            0 :          m_setx2 = m_defSetx2;
     871            0 :          m_sety2 = m_defSety2;
     872            0 :          m_setD2 = m_defSetD2;
     873              : 
     874            0 :          m_setx3 = m_defSetx3;
     875            0 :          m_sety3 = m_defSety3;
     876            0 :          m_setD3 = m_defSetD3;
     877              : 
     878            0 :          if(m_numPupils == 4)
     879              :          {
     880            0 :             m_setx4 = m_defSetx4;
     881            0 :             m_sety4 = m_defSety4;
     882            0 :             m_setD4 = m_defSetD4;
     883              :          }
     884            0 :          log<text_log>("Set default set-points");
     885              :       }
     886              :    }
     887              : 
     888              :    uint32_t imsize[3];
     889            0 :    imsize[0] = shmimMonitorT::m_width;
     890            0 :    imsize[1] = shmimMonitorT::m_height;
     891            0 :    imsize[2] = 1;
     892              : 
     893            0 :    if(m_threshShmimConnected)
     894              :    {
     895            0 :       ImageStreamIO_destroyIm( &m_threshShmim );
     896            0 :       m_threshShmimConnected = false;
     897              :    }
     898              : 
     899            0 :    if(m_edgeShmimConnected)
     900              :    {
     901            0 :       ImageStreamIO_destroyIm( &m_edgeShmim );
     902            0 :       m_edgeShmimConnected = false;
     903              :    }
     904              : 
     905            0 :    ImageStreamIO_createIm_gpu(&m_threshShmim , m_threshShmimName.c_str(), 3, imsize, shmimMonitorT::m_dataType, -1, 1, IMAGE_NB_SEMAPHORE, 0, CIRCULAR_BUFFER | ZAXIS_TEMPORAL,0);
     906            0 :    m_threshShmimConnected = true;
     907              : 
     908            0 :    ImageStreamIO_createIm_gpu(&m_edgeShmim , m_edgeShmimName.c_str(), 3, imsize, shmimMonitorT::m_dataType, -1, 1, IMAGE_NB_SEMAPHORE, 0, CIRCULAR_BUFFER | ZAXIS_TEMPORAL,0);
     909            0 :    m_edgeShmimConnected = true;
     910              : 
     911              : 
     912            0 :    return 0;
     913            0 : }
     914              : 
     915              : inline
     916            0 : int pupilFit::processImage( void* curr_src,
     917              :                             const dev::shmimT & dummy
     918              :                           )
     919              : {
     920              :    static_cast<void>(dummy);
     921              : 
     922            0 :    for(unsigned nn=0; nn < shmimMonitorT::m_width*shmimMonitorT::m_height; ++nn)
     923              :    {
     924            0 :       m_fitIm.data()[nn] = (reinterpret_cast<float *>(curr_src)) [nn];
     925              :    }
     926              : 
     927            0 :    m_fitter.m_thresh = m_threshold;
     928              : 
     929            0 :    m_fitter.fit(m_fitIm, m_edgeIm);
     930              : 
     931              : 
     932              :    {//mutex scope
     933              : 
     934            0 :       std::lock_guard<std::mutex> guard(m_indiMutex);
     935            0 :       m_indiP_quad1["set-x"].set(m_setx1);
     936            0 :       m_indiP_quad1["x"].set(m_fitter.m_avgx[0]);
     937            0 :       m_indiP_quad1["dx"].set(m_fitter.m_avgx[0]-m_setx1);
     938            0 :       m_indiP_quad1["set-y"].set(m_sety1);
     939            0 :       m_indiP_quad1["y"].set(m_fitter.m_avgy[0]);
     940            0 :       m_indiP_quad1["dy"].set(m_fitter.m_avgy[0]-m_sety1);
     941            0 :       m_indiP_quad1["set-D"].set(m_setD1);
     942            0 :       m_indiP_quad1["D"].set(2*m_fitter.m_avgr[0]);
     943            0 :       m_indiP_quad1["dD"].set(2*m_fitter.m_avgr[0]-m_setD1);
     944            0 :       m_indiP_quad1["med"].set(m_fitter.m_med[0]);
     945            0 :       m_indiP_quad1["bg"].set(m_fitter.m_bg[0]);
     946            0 :       m_indiP_quad1.setState (INDI_BUSY);
     947            0 :       m_indiDriver->sendSetProperty (m_indiP_quad1);
     948              : 
     949            0 :       m_indiP_quad2["set-x"].set(m_setx2);
     950            0 :       m_indiP_quad2["x"].set(m_fitter.m_avgx[1]);
     951            0 :       m_indiP_quad2["dx"].set(m_fitter.m_avgx[1]-m_setx2);
     952            0 :       m_indiP_quad2["set-y"].set(m_sety2);
     953            0 :       m_indiP_quad2["y"].set(m_fitter.m_avgy[1]);
     954            0 :       m_indiP_quad2["dy"].set(m_fitter.m_avgy[1]-m_sety2);
     955            0 :       m_indiP_quad2["set-D"].set(m_setD2);
     956            0 :       m_indiP_quad2["D"].set(2*m_fitter.m_avgr[1]);
     957            0 :       m_indiP_quad2["dD"].set(2*m_fitter.m_avgr[1]-m_setD2);
     958            0 :       m_indiP_quad2["med"].set(m_fitter.m_med[1]);
     959            0 :       m_indiP_quad2["bg"].set(m_fitter.m_bg[1]);
     960            0 :       m_indiP_quad2.setState (INDI_BUSY);
     961            0 :       m_indiDriver->sendSetProperty (m_indiP_quad2);
     962              : 
     963            0 :       m_indiP_quad3["set-x"].set(m_setx3);
     964            0 :       m_indiP_quad3["x"].set(m_fitter.m_avgx[2]);
     965            0 :       m_indiP_quad3["dx"].set(m_fitter.m_avgx[2]-m_setx3);
     966            0 :       m_indiP_quad3["set-y"].set(m_sety3);
     967            0 :       m_indiP_quad3["y"].set(m_fitter.m_avgy[2]);
     968            0 :       m_indiP_quad3["dy"].set(m_fitter.m_avgy[2]-m_sety3);
     969            0 :       m_indiP_quad3["set-D"].set(m_setD3);
     970            0 :       m_indiP_quad3["D"].set(2*m_fitter.m_avgr[2]);
     971            0 :       m_indiP_quad3["dD"].set(2*m_fitter.m_avgr[2]-m_setD3);
     972            0 :       m_indiP_quad3["med"].set(m_fitter.m_med[2]);
     973            0 :       m_indiP_quad3["bg"].set(m_fitter.m_bg[2]);
     974            0 :       m_indiP_quad3.setState (INDI_BUSY);
     975            0 :       m_indiDriver->sendSetProperty (m_indiP_quad3);
     976              : 
     977            0 :       if(m_numPupils == 3)
     978              :       {
     979            0 :          m_indiP_avg["x"].set(.333*(m_fitter.m_avgx[0] + m_fitter.m_avgx[1] + m_fitter.m_avgx[2]));
     980            0 :          m_indiP_avg["y"].set(.333*(m_fitter.m_avgy[0] + m_fitter.m_avgy[1] + m_fitter.m_avgy[2]));
     981            0 :          m_indiP_avg["D"].set(.667*(m_fitter.m_avgr[0] + m_fitter.m_avgr[1] + m_fitter.m_avgr[2]));
     982              : 
     983            0 :          m_avg_dx = .333*(m_fitter.m_avgx[0] + m_fitter.m_avgx[1] + m_fitter.m_avgx[2] + m_fitter.m_avgx[3]) - 0.25*(m_setx1 + m_setx2 + m_setx3 + m_setx4);
     984            0 :          m_avg_dy = .333*(m_fitter.m_avgy[0] + m_fitter.m_avgy[1] + m_fitter.m_avgy[2] + m_fitter.m_avgy[3]) - 0.25*(m_sety1 + m_sety2 + m_sety3 + m_sety4);
     985              : 
     986              : 
     987            0 :          m_indiP_avg["dx"].set(.333*(m_fitter.m_avgx[0] + m_fitter.m_avgx[1] + m_fitter.m_avgx[2]) - 0.333*(m_setx1 + m_setx2 + m_setx3));
     988            0 :          m_indiP_avg["dy"].set(.333*(m_fitter.m_avgy[0] + m_fitter.m_avgy[1] + m_fitter.m_avgy[2]) - 0.333*(m_sety1 + m_sety2 + m_sety3));
     989            0 :          m_indiP_avg["dD"].set(.667*(m_fitter.m_avgr[0] + m_fitter.m_avgr[1] + m_fitter.m_avgr[2]) - 0.333*(m_setD1 + m_setD2 + m_setD3));
     990              :       }
     991              :       else
     992              :       {
     993            0 :          m_indiP_quad4["set-x"].set(m_setx4);
     994            0 :          m_indiP_quad4["x"].set(m_fitter.m_avgx[3]);
     995            0 :          m_indiP_quad4["dx"].set(m_fitter.m_avgx[3]-m_setx4);
     996            0 :          m_indiP_quad4["set-y"].set(m_sety4);
     997            0 :          m_indiP_quad4["y"].set(m_fitter.m_avgy[3]);
     998            0 :          m_indiP_quad4["dy"].set(m_fitter.m_avgy[3]-m_sety4);
     999            0 :          m_indiP_quad4["set-D"].set(m_setD4);
    1000            0 :          m_indiP_quad4["D"].set(2*m_fitter.m_avgr[3]);
    1001            0 :          m_indiP_quad4["dD"].set(2*m_fitter.m_avgr[3]-m_setD4);
    1002            0 :          m_indiP_quad4["med"].set(m_fitter.m_med[3]);
    1003            0 :          m_indiP_quad4["bg"].set(m_fitter.m_bg[3]);
    1004            0 :          m_indiP_quad4.setState (INDI_BUSY);
    1005            0 :          m_indiDriver->sendSetProperty (m_indiP_quad4);
    1006              : 
    1007            0 :          m_indiP_avg["x"].set(.25*(m_fitter.m_avgx[0] + m_fitter.m_avgx[1] + m_fitter.m_avgx[2] + m_fitter.m_avgx[3]));
    1008            0 :          m_indiP_avg["y"].set(.25*(m_fitter.m_avgy[0] + m_fitter.m_avgy[1] + m_fitter.m_avgy[2] + m_fitter.m_avgy[3]));
    1009            0 :          m_indiP_avg["D"].set(.5*(m_fitter.m_avgr[0] + m_fitter.m_avgr[1] + m_fitter.m_avgr[2] + m_fitter.m_avgr[3]));
    1010              : 
    1011            0 :          m_avg_dx = .25*(m_fitter.m_avgx[0] + m_fitter.m_avgx[1] + m_fitter.m_avgx[2] + m_fitter.m_avgx[3]) - 0.25*(m_setx1 + m_setx2 + m_setx3 + m_setx4);
    1012            0 :          m_avg_dy = .25*(m_fitter.m_avgy[0] + m_fitter.m_avgy[1] + m_fitter.m_avgy[2] + m_fitter.m_avgy[3]) - 0.25*(m_sety1 + m_sety2 + m_sety3 + m_sety4);
    1013              : 
    1014            0 :          m_indiP_avg["dx"].set(.25*(m_fitter.m_avgx[0] + m_fitter.m_avgx[1] + m_fitter.m_avgx[2] + m_fitter.m_avgx[3]) - 0.25*(m_setx1 + m_setx2 + m_setx3 + m_setx4));
    1015            0 :          m_indiP_avg["dy"].set(.25*(m_fitter.m_avgy[0] + m_fitter.m_avgy[1] + m_fitter.m_avgy[2] + m_fitter.m_avgy[3]) - 0.25*(m_sety1 + m_sety2 + m_sety3 + m_sety4));
    1016            0 :          m_indiP_avg["dD"].set(.5*(m_fitter.m_avgr[0] + m_fitter.m_avgr[1] + m_fitter.m_avgr[2] + m_fitter.m_avgr[3]) - 0.25*(m_setD1 + m_setD2 + m_setD3 + m_setD4));
    1017            0 :          m_indiDriver->sendSetProperty (m_indiP_avg);
    1018              : 
    1019              :       }
    1020              : 
    1021            0 :    }
    1022              : 
    1023              :    //signal framegrabber
    1024              : //Now tell the f.g. to get going
    1025            0 :    m_updated = true;
    1026            0 :    if(sem_post(&m_smSemaphore) < 0)
    1027              :    {
    1028            0 :       log<software_critical>({__FILE__, __LINE__, errno, 0, "Error posting to semaphore"});
    1029            0 :       return -1;
    1030              :    }
    1031              : 
    1032              : 
    1033            0 :    if(m_averaging)
    1034              :    {
    1035            0 :       ++m_navg;
    1036              : 
    1037            0 :       m_avgx1_accum += m_fitter.m_avgx[0];
    1038            0 :       m_avgx1sq_accum += m_fitter.m_avgx[0]*m_fitter.m_avgx[0];
    1039              : 
    1040            0 :       m_avgy1_accum += m_fitter.m_avgy[0];
    1041            0 :       m_avgy1sq_accum += m_fitter.m_avgy[0]*m_fitter.m_avgy[0];
    1042              : 
    1043            0 :       m_avgD1_accum += 2*m_fitter.m_avgr[0];
    1044            0 :       m_avgD1sq_accum += 4*m_fitter.m_avgr[0]*m_fitter.m_avgr[0];
    1045              : 
    1046            0 :       m_avgmed1_accum += m_fitter.m_med[0];
    1047            0 :       m_avgmed1sq_accum += m_fitter.m_med[0]*m_fitter.m_med[0];
    1048              : 
    1049            0 :       m_avgx1 = m_avgx1_accum / m_navg;
    1050            0 :       m_varx1 = m_avgx1sq_accum / m_navg - m_avgx1*m_avgx1;
    1051              : 
    1052            0 :       m_avgy1 = m_avgy1_accum / m_navg;
    1053            0 :       m_vary1 = m_avgy1sq_accum / m_navg - m_avgy1*m_avgy1;
    1054              : 
    1055            0 :       m_avgD1 = m_avgD1_accum / m_navg;
    1056            0 :       m_varD1 = m_avgD1sq_accum / m_navg - m_avgD1*m_avgD1;
    1057              : 
    1058            0 :       m_avgmed1 = m_avgmed1_accum / m_navg;
    1059            0 :       m_varmed1 = m_avgmed1sq_accum / m_navg - m_avgmed1*m_avgmed1;
    1060              : 
    1061            0 :       m_avgx2_accum += m_fitter.m_avgx[1];
    1062            0 :       m_avgx2sq_accum += m_fitter.m_avgx[1]*m_fitter.m_avgx[1];
    1063              : 
    1064            0 :       m_avgy2_accum += m_fitter.m_avgy[1];
    1065            0 :       m_avgy2sq_accum += m_fitter.m_avgy[1]*m_fitter.m_avgy[1];
    1066              : 
    1067            0 :       m_avgD2_accum += 2*m_fitter.m_avgr[1];
    1068            0 :       m_avgD2sq_accum += 4*m_fitter.m_avgr[1]*m_fitter.m_avgr[1];
    1069              : 
    1070            0 :       m_avgmed2_accum += m_fitter.m_med[1];
    1071            0 :       m_avgmed2sq_accum += m_fitter.m_med[1]*m_fitter.m_med[1];
    1072              : 
    1073            0 :       m_avgx2 = m_avgx2_accum / m_navg;
    1074            0 :       m_varx2 = m_avgx2sq_accum / m_navg - m_avgx2*m_avgx2;
    1075              : 
    1076            0 :       m_avgy2 = m_avgy2_accum / m_navg;
    1077            0 :       m_vary2 = m_avgy2sq_accum / m_navg - m_avgy2*m_avgy2;
    1078              : 
    1079            0 :       m_avgD2 = m_avgD2_accum / m_navg;
    1080            0 :       m_varD2 = m_avgD2sq_accum / m_navg - m_avgD2*m_avgD2;
    1081              : 
    1082            0 :       m_avgmed2 = m_avgmed2_accum / m_navg;
    1083            0 :       m_varmed2 = m_avgmed2sq_accum / m_navg - m_avgmed2*m_avgmed2;
    1084              : 
    1085              : 
    1086              : 
    1087            0 :       m_avgx3_accum += m_fitter.m_avgx[2];
    1088            0 :       m_avgx3sq_accum += m_fitter.m_avgx[2]*m_fitter.m_avgx[2];
    1089              : 
    1090            0 :       m_avgy3_accum += m_fitter.m_avgy[2];
    1091            0 :       m_avgy3sq_accum += m_fitter.m_avgy[2]*m_fitter.m_avgy[2];
    1092              : 
    1093            0 :       m_avgD3_accum += 2*m_fitter.m_avgr[2];
    1094            0 :       m_avgD3sq_accum += 4*m_fitter.m_avgr[2]*m_fitter.m_avgr[2];
    1095              : 
    1096            0 :       m_avgmed3_accum += m_fitter.m_med[2];
    1097            0 :       m_avgmed3sq_accum += m_fitter.m_med[2]*m_fitter.m_med[2];
    1098              : 
    1099            0 :       m_avgx3 = m_avgx3_accum / m_navg;
    1100            0 :       m_varx3 = m_avgx3sq_accum / m_navg - m_avgx3*m_avgx3;
    1101              : 
    1102            0 :       m_avgy3 = m_avgy3_accum / m_navg;
    1103            0 :       m_vary3 = m_avgy3sq_accum / m_navg - m_avgy3*m_avgy3;
    1104              : 
    1105            0 :       m_avgD3 = m_avgD3_accum / m_navg;
    1106            0 :       m_varD3 = m_avgD3sq_accum / m_navg - m_avgD3*m_avgD3;
    1107              : 
    1108            0 :       m_avgmed3 = m_avgmed3_accum / m_navg;
    1109            0 :       m_varmed3 = m_avgmed3sq_accum / m_navg - m_avgmed3*m_avgmed3;
    1110              : 
    1111            0 :       if(m_numPupils == 3)
    1112              :       {
    1113            0 :          float tmp = 0.333*(m_fitter.m_avgx[0]+m_fitter.m_avgx[1]+m_fitter.m_avgx[2]+m_fitter.m_avgx[3]);
    1114            0 :          m_avgxAll_accum += tmp;
    1115            0 :          m_avgxAllsq_accum += tmp*tmp;
    1116              : 
    1117            0 :          tmp = 0.333*(m_fitter.m_avgy[0]+m_fitter.m_avgy[1]+m_fitter.m_avgy[2]);
    1118            0 :          m_avgyAll_accum += tmp;
    1119            0 :          m_avgyAllsq_accum += tmp*tmp;
    1120              : 
    1121            0 :          tmp = 2*0.333*(m_fitter.m_avgr[0]+m_fitter.m_avgr[1]+m_fitter.m_avgr[2]);
    1122            0 :          m_avgDAll_accum += tmp;
    1123            0 :          m_avgDAllsq_accum += tmp*tmp;
    1124              : 
    1125            0 :          tmp = 0.333*(m_fitter.m_med[0]+m_fitter.m_med[1]+m_fitter.m_med[2]);
    1126            0 :          m_avgmedAll_accum += tmp;
    1127            0 :          m_avgmedAllsq_accum += tmp*tmp;
    1128              : 
    1129            0 :          m_avgxAll = m_avgxAll_accum / m_navg;
    1130            0 :          m_varxAll = m_avgxAllsq_accum / m_navg - m_avgxAll*m_avgxAll;
    1131              : 
    1132            0 :          m_avgyAll = m_avgyAll_accum / m_navg;
    1133            0 :          m_varyAll = m_avgyAllsq_accum / m_navg - m_avgyAll*m_avgyAll;
    1134              : 
    1135            0 :          m_avgDAll = m_avgDAll_accum / m_navg;
    1136            0 :          m_varDAll = m_avgDAllsq_accum / m_navg - m_avgDAll*m_avgDAll;
    1137              : 
    1138            0 :          m_avgmedAll = m_avgmedAll_accum / m_navg;
    1139            0 :          m_varmedAll = m_avgmedAllsq_accum / m_navg - m_avgmedAll*m_avgmedAll;
    1140              : 
    1141              : 
    1142            0 :          std::cerr << "****************************************************************\n";
    1143            0 :          std::cerr << "Averaged: " << m_navg << "\n";
    1144            0 :          std::cerr << "Average x1: " << m_avgx1 << " +/- " << sqrt(m_varx1) << "\n";
    1145            0 :          std::cerr << "Average y1: " << m_avgy1 << " +/- " << sqrt(m_vary1) << "\n";
    1146            0 :          std::cerr << "Average D1: " << m_avgD1 << " +/- " << sqrt(m_varD1) << "\n";
    1147            0 :          std::cerr << "Average med1: " << m_avgmed1 << " +/- " << sqrt(m_varmed1) << "\n\n";
    1148            0 :          std::cerr << "Average x2: " << m_avgx2 << " +/- " << sqrt(m_varx2) << "\n";
    1149            0 :          std::cerr << "Average y2: " << m_avgy2 << " +/- " << sqrt(m_vary2) << "\n";
    1150            0 :          std::cerr << "Average D2: " << m_avgD2 << " +/- " << sqrt(m_varD2) << "\n";
    1151            0 :          std::cerr << "Average med2: " << m_avgmed2 << " +/- " << sqrt(m_varmed2) << "\n\n";
    1152            0 :          std::cerr << "Average x3: " << m_avgx3 << " +/- " << sqrt(m_varx3) << "\n";
    1153            0 :          std::cerr << "Average y3: " << m_avgy3 << " +/- " << sqrt(m_vary3) << "\n";
    1154            0 :          std::cerr << "Average D3: " << m_avgD3 << " +/- " << sqrt(m_varD3) << "\n";
    1155            0 :          std::cerr << "Average med3: " << m_avgmed3 << " +/- " << sqrt(m_varmed3) << "\n\n";
    1156            0 :          std::cerr << "Average xAll: " << m_avgxAll << " +/- " << sqrt(m_varxAll) << "\n";
    1157            0 :          std::cerr << "Average yAll: " << m_avgyAll << " +/- " << sqrt(m_varyAll) << "\n";
    1158            0 :          std::cerr << "Average DAll: " << m_avgDAll << " +/- " << sqrt(m_varDAll) << "\n";
    1159            0 :          std::cerr << "Average medAll: " << m_avgmedAll << " +/- " << sqrt(m_varmedAll) << "\n\n";
    1160              :       }
    1161              :       else
    1162              :       {
    1163            0 :          m_avgx4_accum += m_fitter.m_avgx[3];
    1164            0 :          m_avgx4sq_accum += m_fitter.m_avgx[3]*m_fitter.m_avgx[3];
    1165              : 
    1166            0 :          m_avgy4_accum += m_fitter.m_avgy[3];
    1167            0 :          m_avgy4sq_accum += m_fitter.m_avgy[3]*m_fitter.m_avgy[3];
    1168              : 
    1169            0 :          m_avgD4_accum += 2*m_fitter.m_avgr[3];
    1170            0 :          m_avgD4sq_accum += 4*m_fitter.m_avgr[3]*m_fitter.m_avgr[3];
    1171              : 
    1172            0 :          m_avgmed4_accum += m_fitter.m_med[3];
    1173            0 :          m_avgmed4sq_accum += m_fitter.m_med[3]*m_fitter.m_med[3];
    1174              : 
    1175            0 :          m_avgx4 = m_avgx4_accum / m_navg;
    1176            0 :          m_varx4 = m_avgx4sq_accum / m_navg - m_avgx4*m_avgx4;
    1177              : 
    1178            0 :          m_avgy4 = m_avgy4_accum / m_navg;
    1179            0 :          m_vary4 = m_avgy4sq_accum / m_navg - m_avgy4*m_avgy4;
    1180              : 
    1181            0 :          m_avgD4 = m_avgD4_accum / m_navg;
    1182            0 :          m_varD4 = m_avgD4sq_accum / m_navg - m_avgD4*m_avgD4;
    1183              : 
    1184            0 :          m_avgmed4 = m_avgmed4_accum / m_navg;
    1185            0 :          m_varmed4 = m_avgmed4sq_accum / m_navg - m_avgmed4*m_avgmed4;
    1186              : 
    1187              : 
    1188            0 :          float tmp = 0.25*(m_fitter.m_avgx[0]+m_fitter.m_avgx[1]+m_fitter.m_avgx[2]+m_fitter.m_avgx[3]);
    1189            0 :          m_avgxAll_accum += tmp;
    1190            0 :          m_avgxAllsq_accum += tmp*tmp;
    1191              : 
    1192            0 :          tmp = 0.25*(m_fitter.m_avgy[0]+m_fitter.m_avgy[1]+m_fitter.m_avgy[2]+m_fitter.m_avgy[3]);
    1193            0 :          m_avgyAll_accum += tmp;
    1194            0 :          m_avgyAllsq_accum += tmp*tmp;
    1195              : 
    1196            0 :          tmp = 2*0.25*(m_fitter.m_avgr[0]+m_fitter.m_avgr[1]+m_fitter.m_avgr[2]+m_fitter.m_avgr[3]);
    1197            0 :          m_avgDAll_accum += tmp;
    1198            0 :          m_avgDAllsq_accum += tmp*tmp;
    1199              : 
    1200            0 :          tmp = 0.25*(m_fitter.m_med[0]+m_fitter.m_med[1]+m_fitter.m_med[2]+m_fitter.m_med[3]);
    1201            0 :          m_avgmedAll_accum += tmp;
    1202            0 :          m_avgmedAllsq_accum += tmp*tmp;
    1203              : 
    1204            0 :          m_avgxAll = m_avgxAll_accum / m_navg;
    1205            0 :          m_varxAll = m_avgxAllsq_accum / m_navg - m_avgxAll*m_avgxAll;
    1206              : 
    1207            0 :          m_avgyAll = m_avgyAll_accum / m_navg;
    1208            0 :          m_varyAll = m_avgyAllsq_accum / m_navg - m_avgyAll*m_avgyAll;
    1209              : 
    1210            0 :          m_avgDAll = m_avgDAll_accum / m_navg;
    1211            0 :          m_varDAll = m_avgDAllsq_accum / m_navg - m_avgDAll*m_avgDAll;
    1212              : 
    1213            0 :          m_avgmedAll = m_avgmedAll_accum / m_navg;
    1214            0 :          m_varmedAll = m_avgmedAllsq_accum / m_navg - m_avgmedAll*m_avgmedAll;
    1215              : 
    1216              : 
    1217            0 :          std::cerr << "****************************************************************\n";
    1218            0 :          std::cerr << "Averaged: " << m_navg << "\n";
    1219            0 :          std::cerr << "Average x1: " << m_avgx1 << " +/- " << sqrt(m_varx1) << "\n";
    1220            0 :          std::cerr << "Average y1: " << m_avgy1 << " +/- " << sqrt(m_vary1) << "\n";
    1221            0 :          std::cerr << "Average D1: " << m_avgD1 << " +/- " << sqrt(m_varD1) << "\n";
    1222            0 :          std::cerr << "Average med1: " << m_avgmed1 << " +/- " << sqrt(m_varmed1) << "\n\n";
    1223            0 :          std::cerr << "Average x2: " << m_avgx2 << " +/- " << sqrt(m_varx2) << "\n";
    1224            0 :          std::cerr << "Average y2: " << m_avgy2 << " +/- " << sqrt(m_vary2) << "\n";
    1225            0 :          std::cerr << "Average D2: " << m_avgD2 << " +/- " << sqrt(m_varD2) << "\n";
    1226            0 :          std::cerr << "Average med2: " << m_avgmed2 << " +/- " << sqrt(m_varmed2) << "\n\n";
    1227            0 :          std::cerr << "Average x3: " << m_avgx3 << " +/- " << sqrt(m_varx3) << "\n";
    1228            0 :          std::cerr << "Average y3: " << m_avgy3 << " +/- " << sqrt(m_vary3) << "\n";
    1229            0 :          std::cerr << "Average D3: " << m_avgD3 << " +/- " << sqrt(m_varD3) << "\n";
    1230            0 :          std::cerr << "Average med3: " << m_avgmed3 << " +/- " << sqrt(m_varmed3) << "\n\n";
    1231            0 :          std::cerr << "Average x4: " << m_avgx4 << " +/- " << sqrt(m_varx4) << "\n";
    1232            0 :          std::cerr << "Average y4: " << m_avgy4 << " +/- " << sqrt(m_vary4) << "\n";
    1233            0 :          std::cerr << "Average D4: " << m_avgD4 << " +/- " << sqrt(m_varD4) << "\n";
    1234            0 :          std::cerr << "Average med4: " << m_avgmed4 << " +/- " << sqrt(m_varmed4) << "\n\n";
    1235            0 :          std::cerr << "Average xAll: " << m_avgxAll << " +/- " << sqrt(m_varxAll) << "\n";
    1236            0 :          std::cerr << "Average yAll: " << m_avgyAll << " +/- " << sqrt(m_varyAll) << "\n";
    1237            0 :          std::cerr << "Average DAll: " << m_avgDAll << " +/- " << sqrt(m_varDAll) << "\n";
    1238            0 :          std::cerr << "Average medAll: " << m_avgmedAll << " +/- " << sqrt(m_varmedAll) << "\n\n";
    1239              :       }
    1240              :    }
    1241              : 
    1242            0 :    m_threshShmim.md->write=1;
    1243            0 :    m_edgeShmim.md->write=1;
    1244              : 
    1245            0 :    clock_gettime(CLOCK_REALTIME, &m_threshShmim.md->writetime);
    1246            0 :    m_edgeShmim.md->writetime = m_threshShmim.md->writetime;
    1247              : 
    1248            0 :    m_threshShmim.md->atime = m_threshShmim.md->writetime;
    1249            0 :    m_edgeShmim.md->atime = m_threshShmim.md->writetime;
    1250              : 
    1251            0 :    m_threshShmim.md->cnt0++;
    1252            0 :    m_edgeShmim.md->cnt0++;
    1253              : 
    1254            0 :    memcpy(m_threshShmim.array.raw, m_fitIm.data(), m_fitIm.rows()*m_fitIm.cols()*sizeof(float));
    1255            0 :    memcpy(m_edgeShmim.array.raw, m_edgeIm.data(), m_edgeIm.rows()*m_edgeIm.cols()*sizeof(float));
    1256              : 
    1257            0 :    m_threshShmim.md->write=0;
    1258            0 :    m_edgeShmim.md->write=0;
    1259              : 
    1260            0 :    ImageStreamIO_sempost(&m_threshShmim,-1);
    1261            0 :    ImageStreamIO_sempost(&m_edgeShmim,-1);
    1262              : 
    1263            0 :    return 0;
    1264              : }
    1265              : 
    1266              : inline
    1267            0 : int pupilFit::allocate(const refShmimT & dummy)
    1268              : {
    1269              :    static_cast<void>(dummy);
    1270              : 
    1271            0 :    std::lock_guard<std::mutex> guard(m_indiMutex);
    1272              : 
    1273            0 :    if(refShmimMonitorT::m_dataType != IMAGESTRUCT_FLOAT)
    1274              :    {
    1275            0 :       return log<software_error,-1>({__FILE__, __LINE__, "reference is not float"});
    1276              :    }
    1277              : 
    1278            0 :    m_refIm.resize( refShmimMonitorT::m_width, refShmimMonitorT::m_height );
    1279              : 
    1280            0 :    return 0;
    1281            0 : }
    1282              : 
    1283              : inline
    1284            0 : int pupilFit::processImage( void* curr_src,
    1285              :                             const refShmimT & dummy
    1286              :                           )
    1287              : {
    1288              :    static_cast<void>(dummy);
    1289              : 
    1290            0 :    int npix = 0;
    1291            0 :    for(unsigned nn=0; nn < refShmimMonitorT::m_width*refShmimMonitorT::m_height; ++nn)
    1292              :    {
    1293            0 :       m_refIm.data()[nn] = (reinterpret_cast<float *>(curr_src)) [nn];
    1294            0 :       ++npix;
    1295              :    }
    1296              : 
    1297            0 :    log<text_log>("reference updated", logPrio::LOG_NOTICE);
    1298              : 
    1299            0 :    std::cerr << m_refIm.sum() << " " << npix << "\n";
    1300              : 
    1301            0 :    shmimMonitorT::m_restart = true;
    1302              : 
    1303            0 :    return 0;
    1304              : }
    1305              : 
    1306              : inline
    1307            0 : int pupilFit::configureAcquisition()
    1308              : {
    1309            0 :    std::unique_lock<std::mutex> lock(m_indiMutex);
    1310              : 
    1311            0 :    frameGrabberT::m_width = 2;
    1312            0 :    frameGrabberT::m_height = 1;
    1313            0 :    frameGrabberT::m_dataType = _DATATYPE_FLOAT;
    1314              : 
    1315            0 :    return 0;
    1316            0 : }
    1317              : 
    1318              : inline
    1319            0 : int pupilFit::startAcquisition()
    1320              : {
    1321            0 :    return 0;
    1322              : }
    1323              : 
    1324              : inline
    1325            0 : int pupilFit::acquireAndCheckValid()
    1326              : {
    1327              :    timespec ts;
    1328              : 
    1329            0 :    if(clock_gettime(CLOCK_REALTIME, &ts) < 0)
    1330              :    {
    1331            0 :       log<software_critical>({__FILE__,__LINE__,errno,0,"clock_gettime"});
    1332            0 :       return -1;
    1333              :    }
    1334              : 
    1335            0 :    ts.tv_sec += 1;
    1336              : 
    1337            0 :    if(sem_timedwait(&m_smSemaphore, &ts) == 0)
    1338              :    {
    1339            0 :       if( m_updated )
    1340              :       {
    1341            0 :          clock_gettime(CLOCK_REALTIME, &m_currImageTimestamp);
    1342            0 :          return 0;
    1343              :       }
    1344              :       else
    1345              :       {
    1346            0 :          return 1;
    1347              :       }
    1348              :    }
    1349              :    else
    1350              :    {
    1351            0 :       return 1;
    1352              :    }
    1353              : }
    1354              : 
    1355              : inline
    1356            0 : int pupilFit::loadImageIntoStream(void * dest)
    1357              : {
    1358            0 :    (reinterpret_cast<float *>(dest))[0] = m_avg_dx;
    1359            0 :    (reinterpret_cast<float *>(dest))[1] = m_avg_dy;
    1360              : 
    1361            0 :    m_updated = false;
    1362            0 :    return 0;
    1363              : }
    1364              : 
    1365              : inline
    1366            0 : int pupilFit::reconfig()
    1367              : {
    1368            0 :    return 0;
    1369              : }
    1370              : 
    1371            0 : INDI_NEWCALLBACK_DEFN(pupilFit, m_indiP_thresh)(const pcf::IndiProperty & ipRecv)
    1372              : {
    1373            0 :    if(ipRecv.getName() != m_indiP_thresh.getName())
    1374              :    {
    1375            0 :       log<software_error>({__FILE__,__LINE__, "wrong INDI property received."});
    1376            0 :       return -1;
    1377              :    }
    1378              : 
    1379              :    float target;
    1380              : 
    1381            0 :    if( indiTargetUpdate( m_indiP_thresh, target, ipRecv, true) < 0)
    1382              :    {
    1383            0 :       log<software_error>({__FILE__,__LINE__});
    1384            0 :       return -1;
    1385              :    }
    1386              : 
    1387            0 :    m_threshold = target;
    1388              : 
    1389            0 :    if(m_setPointSource == USEREFIM) shmimMonitorT::m_restart = true; //need to re-process the reference
    1390              : 
    1391            0 :    log<text_log>("set threshold = " + std::to_string(m_threshold), logPrio::LOG_NOTICE);
    1392            0 :    return 0;
    1393              : }
    1394              : 
    1395            0 : INDI_NEWCALLBACK_DEFN(pupilFit, m_indiP_averaging)(const pcf::IndiProperty & ipRecv)
    1396              : {
    1397            0 :    if(ipRecv.getName() != m_indiP_averaging.getName())
    1398              :    {
    1399            0 :       log<software_error>({__FILE__,__LINE__, "wrong INDI property received."});
    1400            0 :       return -1;
    1401              :    }
    1402              : 
    1403            0 :    if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On)
    1404              :    {
    1405              : 
    1406            0 :       m_avgx1_accum = 0;
    1407            0 :       m_avgx1sq_accum = 0;
    1408            0 :       m_avgy1_accum = 0;
    1409            0 :       m_avgy1sq_accum = 0;
    1410            0 :       m_avgD1_accum = 0;
    1411            0 :       m_avgD1sq_accum = 0;
    1412            0 :       m_avgmed1_accum = 0;
    1413            0 :       m_avgmed1sq_accum = 0;
    1414              : 
    1415            0 :       m_avgx2_accum = 0;
    1416            0 :       m_avgx2sq_accum = 0;
    1417            0 :       m_avgy2_accum = 0;
    1418            0 :       m_avgy2sq_accum = 0;
    1419            0 :       m_avgD2_accum = 0;
    1420            0 :       m_avgD2sq_accum = 0;
    1421            0 :       m_avgmed2_accum = 0;
    1422            0 :       m_avgmed2sq_accum = 0;
    1423              : 
    1424            0 :       m_avgx3_accum = 0;
    1425            0 :       m_avgx3sq_accum = 0;
    1426            0 :       m_avgy3_accum = 0;
    1427            0 :       m_avgy3sq_accum = 0;
    1428            0 :       m_avgD3_accum = 0;
    1429            0 :       m_avgD3sq_accum = 0;
    1430            0 :       m_avgmed3_accum = 0;
    1431            0 :       m_avgmed3sq_accum = 0;
    1432              : 
    1433            0 :       m_avgx4_accum = 0;
    1434            0 :       m_avgx4sq_accum = 0;
    1435            0 :       m_avgy4_accum = 0;
    1436            0 :       m_avgy4sq_accum = 0;
    1437            0 :       m_avgD4_accum = 0;
    1438            0 :       m_avgD4sq_accum = 0;
    1439            0 :       m_avgmed4_accum = 0;
    1440            0 :       m_avgmed4sq_accum = 0;
    1441              : 
    1442            0 :       m_avgxAll_accum = 0;
    1443            0 :       m_avgxAllsq_accum = 0;
    1444            0 :       m_avgyAll_accum = 0;
    1445            0 :       m_avgyAllsq_accum = 0;
    1446            0 :       m_avgDAll_accum = 0;
    1447            0 :       m_avgDAllsq_accum = 0;
    1448            0 :       m_avgmedAll_accum = 0;
    1449            0 :       m_avgmedAllsq_accum = 0;
    1450              : 
    1451            0 :       m_navg = 0;
    1452            0 :       m_averaging = true;
    1453              : 
    1454            0 :       updateSwitchIfChanged(m_indiP_averaging, "toggle", pcf::IndiElement::On, INDI_BUSY);
    1455              : 
    1456            0 :       log<text_log>("began averaging");
    1457              : 
    1458              :    }
    1459            0 :    else if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::Off)
    1460              :    {
    1461            0 :       m_averaging = false;
    1462            0 :       updateSwitchIfChanged(m_indiP_averaging, "toggle", pcf::IndiElement::Off, INDI_IDLE);
    1463              : 
    1464            0 :       log<text_log>("stopped averaging");
    1465              :    }
    1466              : 
    1467            0 :    return 0;
    1468              : }
    1469              : 
    1470            0 : INDI_NEWCALLBACK_DEFN(pupilFit, m_indiP_reload)(const pcf::IndiProperty & ipRecv)
    1471              : {
    1472            0 :    if(ipRecv.getName() != m_indiP_reload.getName())
    1473              :    {
    1474            0 :       log<software_error>({__FILE__,__LINE__, "wrong INDI property received."});
    1475            0 :       return -1;
    1476              :    }
    1477              : 
    1478            0 :    if( ipRecv["request"].getSwitchState() == pcf::IndiElement::On)
    1479              :    {
    1480            0 :       log<text_log>("reloading");
    1481            0 :       shmimMonitorT::m_restart = 1;
    1482              :    }
    1483              : 
    1484            0 :    return 0;
    1485              : }
    1486              : 
    1487            0 : INDI_NEWCALLBACK_DEFN(pupilFit, m_indiP_update)(const pcf::IndiProperty & ipRecv)
    1488              : {
    1489            0 :    if(ipRecv.getName() != m_indiP_update.getName())
    1490              :    {
    1491            0 :       log<software_error>({__FILE__,__LINE__, "wrong INDI property received."});
    1492            0 :       return -1;
    1493              :    }
    1494              : 
    1495            0 :    if( ipRecv["request"].getSwitchState() == pcf::IndiElement::On)
    1496              :    {
    1497            0 :       std::lock_guard<std::mutex> guard(m_indiMutex);
    1498              : 
    1499            0 :       m_setx1 =  m_indiP_quad1["x"].get<float>();
    1500            0 :       m_sety1 =  m_indiP_quad1["y"].get<float>();
    1501            0 :       m_setD1 =  m_indiP_quad1["D"].get<float>();
    1502              : 
    1503            0 :       m_setx2 =  m_indiP_quad2["x"].get<float>();
    1504            0 :       m_sety2 =  m_indiP_quad2["y"].get<float>();
    1505            0 :       m_setD2 =  m_indiP_quad2["D"].get<float>();
    1506              : 
    1507            0 :       m_setx3 =  m_indiP_quad3["x"].get<float>();
    1508            0 :       m_sety3 =  m_indiP_quad3["y"].get<float>();
    1509            0 :       m_setD3 =  m_indiP_quad3["D"].get<float>();
    1510              : 
    1511            0 :       log<text_log>("Recorded current set-points: ");
    1512            0 :       log<text_log>("Quad 1 set points: " + std::to_string(m_setx1) + " " +  std::to_string(m_sety1) + " " + std::to_string(m_setD1));
    1513            0 :       log<text_log>("Quad 2 set points: " + std::to_string(m_setx2) + " " +  std::to_string(m_sety2) + " " + std::to_string(m_setD2));
    1514            0 :       log<text_log>("Quad 3 set points: " + std::to_string(m_setx3) + " " +  std::to_string(m_sety3) + " " + std::to_string(m_setD3));
    1515              : 
    1516            0 :       if(m_numPupils == 4)
    1517              :       {
    1518            0 :          m_setx4 =  m_indiP_quad4["x"].get<float>();
    1519            0 :          m_sety4 =  m_indiP_quad4["y"].get<float>();
    1520            0 :          m_setD4 =  m_indiP_quad4["D"].get<float>();
    1521            0 :          log<text_log>("Quad 4 set points: " + std::to_string(m_setx4) + " " +  std::to_string(m_sety4) + " " + std::to_string(m_setD4));
    1522              :       }
    1523              : 
    1524            0 :       if(m_setPointSource == USEUSERSET) shmimMonitorT::m_restart = true;
    1525            0 :    }
    1526              : 
    1527            0 :    return 0;
    1528              : }
    1529              : 
    1530            0 : INDI_NEWCALLBACK_DEFN(pupilFit, m_indiP_refmode)(const pcf::IndiProperty & ipRecv)
    1531              : {
    1532            0 :    if(ipRecv.getName() != m_indiP_refmode.getName())
    1533              :    {
    1534            0 :       log<software_error>({__FILE__,__LINE__, "wrong INDI property received."});
    1535            0 :       return -1;
    1536              :    }
    1537              : 
    1538            0 :    if(ipRecv.find("default"))
    1539              :    {
    1540            0 :       if( ipRecv["default"].getSwitchState() == pcf::IndiElement::On)
    1541              :       {
    1542            0 :          if( m_setPointSource != USEDEFSET)
    1543              :          {
    1544            0 :             log<text_log>("using default reference.", logPrio::LOG_NOTICE);
    1545            0 :             m_setPointSource = USEDEFSET;
    1546            0 :             shmimMonitorT::m_restart = true;
    1547            0 :             return 0;
    1548              :          }
    1549              :       }
    1550              :    }
    1551            0 :    if(ipRecv.find("refim"))
    1552              :    {
    1553            0 :       if( ipRecv["refim"].getSwitchState() == pcf::IndiElement::On)
    1554              :       {
    1555            0 :          if( m_setPointSource != USEREFIM)
    1556              :          {
    1557            0 :             log<text_log>("using reference image.", logPrio::LOG_NOTICE);
    1558            0 :             m_setPointSource = USEREFIM;
    1559            0 :             shmimMonitorT::m_restart = true;
    1560            0 :             return 0;
    1561              :          }
    1562              :       }
    1563              :    }
    1564            0 :    if(ipRecv.find("user"))
    1565              :    {
    1566            0 :       if( ipRecv["user"].getSwitchState() == pcf::IndiElement::On)
    1567              :       {
    1568            0 :          if( m_setPointSource != USEUSERSET)
    1569              :          {
    1570            0 :             log<text_log>("using user image.", logPrio::LOG_NOTICE);
    1571            0 :             m_setPointSource = USEUSERSET;
    1572            0 :             shmimMonitorT::m_restart = true;
    1573            0 :             return 0;
    1574              :          }
    1575              :       }
    1576              :    }
    1577              : 
    1578            0 :    return 0;
    1579              : }
    1580              : 
    1581              : inline
    1582            0 : int pupilFit::checkRecordTimes()
    1583              : {
    1584            0 :    return telemeterT::checkRecordTimes(telem_fgtimings());
    1585              : }
    1586              : 
    1587              : inline
    1588            0 : int pupilFit::recordTelem( const telem_fgtimings * )
    1589              : {
    1590            0 :    return recordFGTimings(true);
    1591              : }
    1592              : 
    1593              : } //namespace app
    1594              : } //namespace MagAOX
    1595              : 
    1596              : #endif //pupilFit_hpp
        

Generated by: LCOV version 2.0-1