API
pupilFit.hpp
Go to the documentation of this file.
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  static std::string configSection()
36  {
37  return "refShmim";
38  };
39 
40  static std::string indiPrefix()
41  {
42  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
68 
70 
71  //The base frameGrabber type
73 
74  //The base telemeter type
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 
107 
110 
111  IMAGE m_edgeShmim;
112  bool m_edgeShmimConnected {false};
113 
114  double m_defSetx1 {29.5};
115  double m_defSety1 {29.5};
116  double m_defSetD1 {56.0};
117 
118  double m_defSetx2 {89.5};
119  double m_defSety2 {29.5};
120  double m_defSetD2 {56.0};
121 
122  double m_defSetx3 {29.5};
123  double m_defSety3 {89.5};
124  double m_defSetD3 {56.0};
125 
126  double m_defSetx4 {89.5};
127  double m_defSety4 {89.5};
128  double m_defSetD4 {56.0};
129 
130  double m_userSetx1 {29.5};
131  double m_userSety1 {29.5};
132  double m_userSetD1 {56.0};
133 
134  double m_userSetx2 {89.5};
135  double m_userSety2 {29.5};
136  double m_userSetD2 {56.0};
137 
138  double m_userSetx3 {29.5};
139  double m_userSety3 {89.5};
140  double m_userSetD3 {56.0};
141 
142  double m_userSetx4 {89.5};
143  double m_userSety4 {89.5};
144  double m_userSetD4 {56.0};
145 
147 
148  bool m_refUpdated {false}; ///< Flag set if the online reference update is used.
149 
150  double m_setx1 {29.5};
151  double m_sety1 {29.5};
152  double m_setD1 {56.0};
153 
154  double m_setx2 {89.5};
155  double m_sety2 {29.5};
156  double m_setD2 {56.0};
157 
158  double m_setx3 {29.5};
159  double m_sety3 {89.5};
160  double m_setD3 {56.0};
161 
162  double m_setx4 {89.5};
163  double m_sety4 {89.5};
164  double m_setD4 {56.0};
165 
166  double m_avg_dx;
167  double m_avg_dy;
168 
169  bool m_averaging {false};
170  size_t m_navg {0};
171 
172  double m_avgx1_accum {0};
173  double m_avgx1sq_accum {0};
174 
175  double m_avgy1_accum {0};
176  double m_avgy1sq_accum {0};
177 
178  double m_avgD1_accum {0};
179  double m_avgD1sq_accum {0};
180 
181  double m_avgmed1_accum {0};
182  double m_avgmed1sq_accum {0};
183 
184  double m_avgx1 {0};
185  double m_varx1 {0};
186 
187  double m_avgy1 {0};
188  double m_vary1 {0};
189 
190  double m_avgD1 {0};
191  double m_varD1 {0};
192 
193  double m_avgmed1 {0};
194  double m_varmed1 {0};
195 
196  double m_avgx2_accum {0};
197  double m_avgx2sq_accum {0};
198 
199  double m_avgy2_accum {0};
200  double m_avgy2sq_accum {0};
201 
202  double m_avgD2_accum {0};
203  double m_avgD2sq_accum {0};
204 
205  double m_avgmed2_accum {0};
206  double m_avgmed2sq_accum {0};
207 
208  double m_avgx2 {0};
209  double m_varx2 {0};
210 
211  double m_avgy2 {0};
212  double m_vary2 {0};
213 
214  double m_avgD2 {0};
215  double m_varD2 {0};
216 
217  double m_avgmed2 {0};
218  double m_varmed2 {0};
219 
220  double m_avgx3_accum {0};
221  double m_avgx3sq_accum {0};
222 
223  double m_avgy3_accum {0};
224  double m_avgy3sq_accum {0};
225 
226  double m_avgD3_accum {0};
227  double m_avgD3sq_accum {0};
228 
229  double m_avgmed3_accum {0};
230  double m_avgmed3sq_accum {0};
231 
232  double m_avgx3 {0};
233  double m_varx3 {0};
234 
235  double m_avgy3 {0};
236  double m_vary3 {0};
237 
238  double m_avgD3 {0};
239  double m_varD3 {0};
240 
241  double m_avgmed3 {0};
242  double m_varmed3 {0};
243 
244  double m_avgx4_accum {0};
245  double m_avgx4sq_accum {0};
246 
247  double m_avgy4_accum {0};
248  double m_avgy4sq_accum {0};
249 
250  double m_avgD4_accum {0};
251  double m_avgD4sq_accum {0};
252 
253  double m_avgmed4_accum {0};
254  double m_avgmed4sq_accum {0};
255 
256  double m_avgx4 {0};
257  double m_varx4 {0};
258 
259  double m_avgy4 {0};
260  double m_vary4 {0};
261 
262  double m_avgD4 {0};
263  double m_varD4 {0};
264 
265  double m_avgmed4 {0};
266  double m_varmed4 {0};
267 
268  double m_avgxAll_accum {0};
269  double m_avgxAllsq_accum {0};
270 
271  double m_avgyAll_accum {0};
272  double m_avgyAllsq_accum {0};
273 
274  double m_avgDAll_accum {0};
275  double m_avgDAllsq_accum {0};
276 
277  double m_avgmedAll_accum {0};
279 
280  double m_avgxAll {0};
281  double m_varxAll {0};
282 
283  double m_avgyAll {0};
284  double m_varyAll {0};
285 
286  double m_avgDAll {0};
287  double m_varDAll {0};
288 
289  double m_avgmedAll {0};
290  double 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  float fps()
366  {
367  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 
409 
410  pcf::IndiProperty 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;
424 
425  pcf::IndiProperty m_indiP_update;
427 
428  pcf::IndiProperty 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 {
448  return;
449 }
450 
451 inline
453 {
455  {
456  ImageStreamIO_destroyIm( &m_threshShmim );
457  }
458 
460  {
461  ImageStreamIO_destroyIm( &m_edgeShmim );
462  }
463 }
464 
465 inline
467 {
471  telemeterT::setupConfig(config);
472 
473  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  config.add("fit.threshold", "", "fit.threshold", argType::Required, "fit", "threshold", false, "float", "The pupil finding threshold. 0 < threshold < 1");
476  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  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  config.add("fit.numPupils", "", "fit.numPupils", argType::Required, "fit", "numPupils", false, "int", "The number of pupils. Default is 4. 3 is also supported.");
480  config.add("fit.pupMedIndex", "", "fit.pupMedIndex", argType::Required, "fit", "pupMedIndex", false, "float", "The index of the pupil median in a sorted quadrant.");
481 
482  config.add("cal.setx1", "", "cal.setx1", argType::Required, "cal", "setx1", false, "float", "The x set point for quad 1 (LL).");
483  config.add("cal.sety1", "", "cal.sety1", argType::Required, "cal", "sety1", false, "float", "The y set point for quad 1 (LL).");
484  config.add("cal.setD1", "", "cal.setD1", argType::Required, "cal", "setD1", false, "float", "The D set point for quad 1 (LL).");
485 
486  config.add("cal.setx2", "", "cal.setx2", argType::Required, "cal", "setx2", false, "float", "The x set point for quad 2 (LL).");
487  config.add("cal.sety2", "", "cal.sety2", argType::Required, "cal", "sety2", false, "float", "The y set point for quad 2 (LL).");
488  config.add("cal.setD2", "", "cal.setD2", argType::Required, "cal", "setD2", false, "float", "The D set point for quad 2 (LL).");
489 
490  config.add("cal.setx3", "", "cal.setx3", argType::Required, "cal", "setx3", false, "float", "The x set point for quad 3 (LL).");
491  config.add("cal.sety3", "", "cal.sety3", argType::Required, "cal", "sety3", false, "float", "The y set point for quad 3 (LL).");
492  config.add("cal.setD3", "", "cal.setD3", argType::Required, "cal", "setD3", false, "float", "The D set point for quad 3 (LL).");
493 
494  config.add("cal.setx4", "", "cal.setx4", argType::Required, "cal", "setx4", false, "float", "The x set point for quad 4 (LL).");
495  config.add("cal.sety4", "", "cal.sety4", argType::Required, "cal", "sety4", false, "float", "The y set point for quad 4 (LL).");
496  config.add("cal.setD4", "", "cal.setD4", argType::Required, "cal", "setD4", false, "float", "The D set point for quad 4 (LL).");
497 }
498 
499 
500 inline
501 int pupilFit::loadConfigImpl( mx::app::appConfigurator & _config )
502 {
503  shmimMonitorT::m_shmimName = "camwfs_avg";
504  shmimMonitorT::loadConfig(_config);
507 
508  frameGrabberT::loadConfig(_config);
509  telemeterT::loadConfig(_config);
510 
511  _config(m_threshold, "fit.threshold");
512  _config(m_threshShmimName, "fit.threshShmimName");
513  _config(m_edgeShmimName, "fit.edgeShmimName");
514  _config(m_numPupils, "fit.numPupils");
515  _config(m_fitter.m_pupMedIndex, "fit.pupMedIndex");
516 
517  _config(m_defSetx1, "cal.setx1");
518  _config(m_defSety1, "cal.sety1");
519  _config(m_defSetD1, "cal.setD1");
520 
521  _config(m_defSetx2, "cal.setx2");
522  _config(m_defSety2, "cal.sety2");
523  _config(m_defSetD2, "cal.setD2");
524 
525  _config(m_defSetx3, "cal.setx3");
526  _config(m_defSety3, "cal.sety3");
527  _config(m_defSetD3, "cal.setD3");
528 
529  _config(m_defSetx4, "cal.setx4");
530  _config(m_defSety4, "cal.sety4");
531  _config(m_defSetD4, "cal.setD4");
532 
533 
534  return 0;
535 }
536 
537 inline
539 {
540  loadConfigImpl(config);
541 }
542 
543 inline
545 {
546  if(shmimMonitorT::appStartup() < 0)
547  {
548  return log<software_error,-1>({__FILE__, __LINE__});
549  }
550 
552  {
553  return log<software_error,-1>({__FILE__, __LINE__});
554  }
555 
556  if(sem_init(&m_smSemaphore, 0,0) < 0)
557  {
558  log<software_critical>({__FILE__, __LINE__, errno,0, "Initializing S.M. semaphore"});
559  return -1;
560  }
561 
562  if(frameGrabberT::appStartup() < 0)
563  {
564  return log<software_error,-1>({__FILE__, __LINE__});
565  }
566 
567  if(telemeterT::appStartup() < 0)
568  {
569  return log<software_error,-1>({__FILE__, __LINE__});
570  }
571 
572  createStandardIndiNumber<float>( m_indiP_thresh, "threshold", 0, 1 ,0, "%0.2f", "Threshold");
573  m_indiP_thresh["current"].set(m_threshold);
574  m_indiP_thresh["target"].set(m_threshold);
576 
577  createStandardIndiToggleSw( m_indiP_averaging, "averaging", "Start/Stop Averaging");
578  m_indiP_averaging["toggle"].set(pcf::IndiElement::Off);
580  {
581  log<software_error>({__FILE__,__LINE__});
582  return -1;
583  }
584 
585  createROIndiNumber( m_indiP_numPupils, "numPupils", "Number of Pupils");
586  indi::addNumberElement<int>( m_indiP_numPupils, "value", 3, 4, 1, "%d", "");
587  m_indiP_numPupils["value"].set(m_numPupils);
589 
590  createROIndiNumber( m_indiP_quad1, "quadrant1", "Quadrant 1");
591  indi::addNumberElement<float>( m_indiP_quad1, "x", 0, 59, 0, "%0.2f", "center x");
592  indi::addNumberElement<float>( m_indiP_quad1, "dx", 0, 59, 0, "%0.2f", "delta-x");
593  indi::addNumberElement<float>( m_indiP_quad1, "y", 0, 59, 0, "%0.2f", "center x");
594  indi::addNumberElement<float>( m_indiP_quad1, "dy", 0, 59, 0, "%0.2f", "delta-y");
595  indi::addNumberElement<float>( m_indiP_quad1, "D", 0, 59, 0, "%0.2f", "diameter");
596  indi::addNumberElement<float>( m_indiP_quad1, "dD", 0, 59, 0, "%0.2f", "delta-D");
597  indi::addNumberElement<float>( m_indiP_quad1, "med", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "flux");
598  indi::addNumberElement<float>( m_indiP_quad1, "bg", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "background");
599  indi::addNumberElement<float>( m_indiP_quad1, "set-x", 0, 59, 0, "%0.2f", "set pt. center x");
600  m_indiP_quad1["set-x"] = m_setx1;
601  indi::addNumberElement<float>( m_indiP_quad1, "set-y", 0, 59, 0, "%0.2f", "set pt. center x");
602  m_indiP_quad1["set-y"] = m_sety1;
603  indi::addNumberElement<float>( m_indiP_quad1, "set-D", 0, 59, 0, "%0.2f", "set pt. diameter");
604  m_indiP_quad1["set-D"] = m_setD1;
605 
607 
608  createROIndiNumber( m_indiP_quad2, "quadrant2", "Quadrant 2");
609  indi::addNumberElement<float>( m_indiP_quad2, "x", 0, 59, 0, "%0.2f", "center x");
610  indi::addNumberElement<float>( m_indiP_quad2, "dx", 0, 59, 0, "%0.2f", "delta-x");
611  indi::addNumberElement<float>( m_indiP_quad2, "y", 0, 59, 0, "%0.2f", "center y");
612  indi::addNumberElement<float>( m_indiP_quad2, "dy", 0, 59, 0, "%0.2f", "delta-y");
613  indi::addNumberElement<float>( m_indiP_quad2, "D", 0, 59, 0, "%0.2f", "diameter");
614  indi::addNumberElement<float>( m_indiP_quad2, "dD", 0, 59, 0, "%0.2f", "delta-D");
615  indi::addNumberElement<float>( m_indiP_quad2, "med", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "flux");
616  indi::addNumberElement<float>( m_indiP_quad2, "bg", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "background");
617  indi::addNumberElement<float>( m_indiP_quad2, "set-x", 0, 59, 0, "%0.2f", "set pt. center x");
618  m_indiP_quad2["set-x"] = m_setx2;
619  indi::addNumberElement<float>( m_indiP_quad2, "set-y", 0, 59, 0, "%0.2f", "set pt. center x");
620  m_indiP_quad2["set-y"] = m_sety2;
621  indi::addNumberElement<float>( m_indiP_quad2, "set-D", 0, 59, 0, "%0.2f", "set pt. diameter");
622  m_indiP_quad2["set-D"] = m_setD2;
624 
625  createROIndiNumber( m_indiP_quad3, "quadrant3", "Quadrant 3");
626  indi::addNumberElement<float>( m_indiP_quad3, "x", 0, 59, 0, "%0.2f", "center x");
627  indi::addNumberElement<float>( m_indiP_quad3, "dx", 0, 59, 0, "%0.2f", "delta-x");
628  indi::addNumberElement<float>( m_indiP_quad3, "y", 0, 59, 0, "%0.2f", "center y");
629  indi::addNumberElement<float>( m_indiP_quad3, "dy", 0, 59, 0, "%0.2f", "delta-y");
630  indi::addNumberElement<float>( m_indiP_quad3, "D", 0, 59, 0, "%0.2f", "diameter");
631  indi::addNumberElement<float>( m_indiP_quad3, "dD", 0, 59, 0, "%0.2f", "delta-D");
632  indi::addNumberElement<float>( m_indiP_quad3, "med", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "flux");
633  indi::addNumberElement<float>( m_indiP_quad3, "bg", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "background");
634  indi::addNumberElement<float>( m_indiP_quad3, "set-x", 0, 59, 0, "%0.2f", "set pt. center x");
635  m_indiP_quad3["set-x"] = m_setx3;
636  indi::addNumberElement<float>( m_indiP_quad3, "set-y", 0, 59, 0, "%0.2f", "set pt. center x");
637  m_indiP_quad3["set-y"] = m_sety3;
638  indi::addNumberElement<float>( m_indiP_quad3, "set-D", 0, 59, 0, "%0.2f", "set pt. diameter");
639  m_indiP_quad3["set-D"] = m_setD3;
641 
642  if(m_numPupils != 3)
643  {
644  createROIndiNumber( m_indiP_quad4, "quadrant4", "Quadrant 4");
645  indi::addNumberElement<float>( m_indiP_quad4, "x", 0, 59, 0, "%0.2f", "center x");
646  indi::addNumberElement<float>( m_indiP_quad4, "dx", 0, 59, 0, "%0.2f", "delta-x");
647  indi::addNumberElement<float>( m_indiP_quad4, "y", 0, 59, 0, "%0.2f", "center y");
648  indi::addNumberElement<float>( m_indiP_quad4, "dy", 0, 59, 0, "%0.2f", "delta-y");
649  indi::addNumberElement<float>( m_indiP_quad4, "D", 0, 59, 0, "%0.2f", "diameter");
650  indi::addNumberElement<float>( m_indiP_quad4, "dD", 0, 59, 0, "%0.2f", "delta-D");
651  indi::addNumberElement<float>( m_indiP_quad4, "med", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "flux");
652  indi::addNumberElement<float>( m_indiP_quad4, "bg", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "background");
653  indi::addNumberElement<float>( m_indiP_quad4, "set-x", 0, 59, 0, "%0.2f", "set pt. center x");
654  m_indiP_quad4["set-x"] = m_setx4;
655  indi::addNumberElement<float>( m_indiP_quad4, "set-y", 0, 59, 0, "%0.2f", "set pt. center x");
656  m_indiP_quad4["set-y"] = m_sety4;
657  indi::addNumberElement<float>( m_indiP_quad4, "set-D", 0, 59, 0, "%0.2f", "set pt. diameter");
658  m_indiP_quad4["set-D"] = m_setD4;
660  }
661 
662  createROIndiNumber( m_indiP_avg, "average", "Average");
663  indi::addNumberElement<float>( m_indiP_avg, "x", 0, 59, 0, "%0.2f", "center x");
664  indi::addNumberElement<float>( m_indiP_avg, "dx", 0, 59, 0, "%0.2f", "delta-x");
665  indi::addNumberElement<float>( m_indiP_avg, "y", 0, 59, 0, "%0.2f", "center y");
666  indi::addNumberElement<float>( m_indiP_avg, "dy", 0, 59, 0, "%0.2f", "delta-y");
667  indi::addNumberElement<float>( m_indiP_avg, "D", 0, 59, 0, "%0.2f", "diameter");
668  indi::addNumberElement<float>( m_indiP_avg, "dD", 0, 59, 0, "%0.2f", "delta-D");
670 
671  createStandardIndiRequestSw( m_indiP_reload, "setpt_reload", "Reload Calibration");
672  m_indiP_reload["request"].set(pcf::IndiElement::Off);
674  {
675  log<software_error>({__FILE__,__LINE__});
676  return -1;
677  }
678 
679  createStandardIndiRequestSw( m_indiP_update, "setpt_current", "Set Reference");
680  m_indiP_update["request"].set(pcf::IndiElement::Off);
682  {
683  log<software_error>({__FILE__,__LINE__});
684  return -1;
685  }
686 
687  createStandardIndiSelectionSw( m_indiP_refmode, "setpt_mode", {"default", "refim", "user"}, "Reference Mode");
689  {
690  m_indiP_refmode["default"].set(pcf::IndiElement::Off);
691  m_indiP_refmode["refim"].set(pcf::IndiElement::On);
692  m_indiP_refmode["user"].set(pcf::IndiElement::Off);
693  }
695  {
696  m_indiP_refmode["default"].set(pcf::IndiElement::Off);
697  m_indiP_refmode["refim"].set(pcf::IndiElement::Off);
698  m_indiP_refmode["user"].set(pcf::IndiElement::On);
699  }
700  else
701  {
702  m_indiP_refmode["default"].set(pcf::IndiElement::On);
703  m_indiP_refmode["refim"].set(pcf::IndiElement::Off);
704  m_indiP_refmode["user"].set(pcf::IndiElement::Off);
705  }
706 
708  {
709  log<software_error>({__FILE__,__LINE__});
710  return -1;
711  }
712 
714 
715  return 0;
716 }
717 
718 inline
720 {
721  if( shmimMonitorT::appLogic() < 0)
722  {
723  return log<software_error,-1>({__FILE__,__LINE__});
724  }
725 
726  if( refShmimMonitorT::appLogic() < 0)
727  {
728  return log<software_error,-1>({__FILE__,__LINE__});
729  }
730 
731  if( frameGrabberT::appLogic() < 0)
732  {
733  return log<software_error,-1>({__FILE__,__LINE__});
734  }
735 
736  if( telemeterT::appLogic() < 0)
737  {
738  return log<software_error,-1>({__FILE__,__LINE__});
739  }
740 
741  std::lock_guard<std::mutex> guard(m_indiMutex);
744 
746  {
747  updateSwitchIfChanged(m_indiP_refmode, "default", pcf::IndiElement::Off);
748  updateSwitchIfChanged(m_indiP_refmode, "refim", pcf::IndiElement::On);
749  updateSwitchIfChanged(m_indiP_refmode, "user", pcf::IndiElement::Off);
750  }
751  else if(m_setPointSource == USEUSERSET)
752  {
753  updateSwitchIfChanged(m_indiP_refmode, "default", pcf::IndiElement::Off);
754  updateSwitchIfChanged(m_indiP_refmode, "refim", pcf::IndiElement::Off);
755  updateSwitchIfChanged(m_indiP_refmode, "user", pcf::IndiElement::On);
756  }
757  else
758  {
759  updateSwitchIfChanged(m_indiP_refmode, "default", pcf::IndiElement::On);
760  updateSwitchIfChanged(m_indiP_refmode, "refim", pcf::IndiElement::Off);
761  updateSwitchIfChanged(m_indiP_refmode, "user", pcf::IndiElement::Off);
762  }
763 
766 
767  if(frameGrabberT::updateINDI() < 0)
768  {
769  log<software_error>({__FILE__, __LINE__});
770  }
771 
772  return 0;
773 }
774 
775 inline
777 {
782 
783  return 0;
784 }
785 
786 inline
787 int pupilFit::allocate(const dev::shmimT & dummy)
788 {
789  static_cast<void>(dummy);
790 
791  std::lock_guard<std::mutex> guard(m_indiMutex);
792 
795 
796  m_fitter.m_numPupils = m_numPupils;
798  m_fitter.m_thresh = m_threshold;
799 
801  {
802  mx::improc::eigenImage<float> refim, refedge;
803  refim = m_refIm; //cuz it's modified by fitter.
804  if(m_fitter.fit(refim, refedge) < 0)
805  {
806  return log<software_error, -1>({__FILE__, __LINE__, "error from fitter for reference"});
807  }
808 
809  m_setx1 = m_fitter.m_avgx[0];
810  m_sety1 = m_fitter.m_avgy[0];
811  m_setD1 = 2*m_fitter.m_avgr[0];
812 
813  m_setx2 = m_fitter.m_avgx[1];
814  m_sety2 = m_fitter.m_avgy[1];
815  m_setD2 = 2*m_fitter.m_avgr[1];
816 
817  m_setx3 = m_fitter.m_avgx[2];
818  m_sety3 = m_fitter.m_avgy[2];
819  m_setD3 = 2*m_fitter.m_avgr[2];
820 
821  m_setx4 = m_fitter.m_avgx[3];
822  m_sety4 = m_fitter.m_avgy[3];
823  m_setD4 = 2*m_fitter.m_avgr[3];
824 
825  log<text_log>("Fit to reference image: ");
826  log<text_log>("Quad 1 set points: " + std::to_string(m_setx1) + " " + std::to_string(m_sety1) + " " + std::to_string(m_setD1));
827  log<text_log>("Quad 2 set points: " + std::to_string(m_setx2) + " " + std::to_string(m_sety2) + " " + std::to_string(m_setD2));
828  log<text_log>("Quad 3 set points: " + std::to_string(m_setx3) + " " + std::to_string(m_sety3) + " " + std::to_string(m_setD3));
829  log<text_log>("Quad 4 set points: " + std::to_string(m_setx4) + " " + std::to_string(m_sety4) + " " + std::to_string(m_setD4));
830  }
831  else
832  {
834  {
835  if(m_refIm.rows()!=0 || m_refIm.cols() != 0) //only complain if the ref image has been loaded
836  {
837  log<text_log>("Reference image size does not match", logPrio::LOG_ERROR);
838  }
839  }
840 
842  {
846 
850 
854 
855  if(m_numPupils == 4)
856  {
860  }
861  log<text_log>("Using user set-points");
862 
863  }
864  else
865  {
869 
873 
877 
878  if(m_numPupils == 4)
879  {
883  }
884  log<text_log>("Set default set-points");
885  }
886  }
887 
888  uint32_t imsize[3];
889  imsize[0] = shmimMonitorT::m_width;
890  imsize[1] = shmimMonitorT::m_height;
891  imsize[2] = 1;
892 
894  {
895  ImageStreamIO_destroyIm( &m_threshShmim );
896  m_threshShmimConnected = false;
897  }
898 
900  {
901  ImageStreamIO_destroyIm( &m_edgeShmim );
902  m_edgeShmimConnected = false;
903  }
904 
905  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  m_threshShmimConnected = true;
907 
908  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  m_edgeShmimConnected = true;
910 
912  {
913  }
914 
915  return 0;
916 }
917 
918 inline
919 int pupilFit::processImage( void* curr_src,
920  const dev::shmimT & dummy
921  )
922 {
923  static_cast<void>(dummy);
924 
925  for(unsigned nn=0; nn < shmimMonitorT::m_width*shmimMonitorT::m_height; ++nn)
926  {
927  m_fitIm.data()[nn] = ((float*)curr_src) [nn];
928  }
929 
930  m_fitter.m_thresh = m_threshold;
931 
932  m_fitter.fit(m_fitIm, m_edgeIm);
933 
934 
935  {//mutex scope
936 
937  std::lock_guard<std::mutex> guard(m_indiMutex);
938  m_indiP_quad1["set-x"].set(m_setx1);
939  m_indiP_quad1["x"].set(m_fitter.m_avgx[0]);
940  m_indiP_quad1["dx"].set(m_fitter.m_avgx[0]-m_setx1);
941  m_indiP_quad1["set-y"].set(m_sety1);
942  m_indiP_quad1["y"].set(m_fitter.m_avgy[0]);
943  m_indiP_quad1["dy"].set(m_fitter.m_avgy[0]-m_sety1);
944  m_indiP_quad1["set-D"].set(m_setD1);
945  m_indiP_quad1["D"].set(2*m_fitter.m_avgr[0]);
946  m_indiP_quad1["dD"].set(2*m_fitter.m_avgr[0]-m_setD1);
947  m_indiP_quad1["med"].set(m_fitter.m_med[0]);
948  m_indiP_quad1["bg"].set(m_fitter.m_bg[0]);
949  m_indiP_quad1.setState (INDI_BUSY);
950  m_indiDriver->sendSetProperty (m_indiP_quad1);
951 
952  m_indiP_quad2["set-x"].set(m_setx2);
953  m_indiP_quad2["x"].set(m_fitter.m_avgx[1]);
954  m_indiP_quad2["dx"].set(m_fitter.m_avgx[1]-m_setx2);
955  m_indiP_quad2["set-y"].set(m_sety2);
956  m_indiP_quad2["y"].set(m_fitter.m_avgy[1]);
957  m_indiP_quad2["dy"].set(m_fitter.m_avgy[1]-m_sety2);
958  m_indiP_quad2["set-D"].set(m_setD2);
959  m_indiP_quad2["D"].set(2*m_fitter.m_avgr[1]);
960  m_indiP_quad2["dD"].set(2*m_fitter.m_avgr[1]-m_setD2);
961  m_indiP_quad2["med"].set(m_fitter.m_med[1]);
962  m_indiP_quad2["bg"].set(m_fitter.m_bg[1]);
963  m_indiP_quad2.setState (INDI_BUSY);
964  m_indiDriver->sendSetProperty (m_indiP_quad2);
965 
966  m_indiP_quad3["set-x"].set(m_setx3);
967  m_indiP_quad3["x"].set(m_fitter.m_avgx[2]);
968  m_indiP_quad3["dx"].set(m_fitter.m_avgx[2]-m_setx3);
969  m_indiP_quad3["set-y"].set(m_sety3);
970  m_indiP_quad3["y"].set(m_fitter.m_avgy[2]);
971  m_indiP_quad3["dy"].set(m_fitter.m_avgy[2]-m_sety3);
972  m_indiP_quad3["set-D"].set(m_setD3);
973  m_indiP_quad3["D"].set(2*m_fitter.m_avgr[2]);
974  m_indiP_quad3["dD"].set(2*m_fitter.m_avgr[2]-m_setD3);
975  m_indiP_quad3["med"].set(m_fitter.m_med[2]);
976  m_indiP_quad3["bg"].set(m_fitter.m_bg[2]);
977  m_indiP_quad3.setState (INDI_BUSY);
978  m_indiDriver->sendSetProperty (m_indiP_quad3);
979 
980  if(m_numPupils == 3)
981  {
982  m_indiP_avg["x"].set(.333*(m_fitter.m_avgx[0] + m_fitter.m_avgx[1] + m_fitter.m_avgx[2]));
983  m_indiP_avg["y"].set(.333*(m_fitter.m_avgy[0] + m_fitter.m_avgy[1] + m_fitter.m_avgy[2]));
984  m_indiP_avg["D"].set(.667*(m_fitter.m_avgr[0] + m_fitter.m_avgr[1] + m_fitter.m_avgr[2]));
985 
986  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);
987  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);
988 
989 
990  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));
991  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));
992  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));
993  }
994  else
995  {
996  m_indiP_quad4["set-x"].set(m_setx4);
997  m_indiP_quad4["x"].set(m_fitter.m_avgx[3]);
998  m_indiP_quad4["dx"].set(m_fitter.m_avgx[3]-m_setx4);
999  m_indiP_quad4["set-y"].set(m_sety4);
1000  m_indiP_quad4["y"].set(m_fitter.m_avgy[3]);
1001  m_indiP_quad4["dy"].set(m_fitter.m_avgy[3]-m_sety4);
1002  m_indiP_quad4["set-D"].set(m_setD4);
1003  m_indiP_quad4["D"].set(2*m_fitter.m_avgr[3]);
1004  m_indiP_quad4["dD"].set(2*m_fitter.m_avgr[3]-m_setD4);
1005  m_indiP_quad4["med"].set(m_fitter.m_med[3]);
1006  m_indiP_quad4["bg"].set(m_fitter.m_bg[3]);
1007  m_indiP_quad4.setState (INDI_BUSY);
1008  m_indiDriver->sendSetProperty (m_indiP_quad4);
1009 
1010  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]));
1011  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]));
1012  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]));
1013 
1014  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);
1015  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);
1016 
1017  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));
1018  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));
1019  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));
1020  m_indiDriver->sendSetProperty (m_indiP_avg);
1021 
1022  }
1023 
1024  }
1025 
1026  //signal framegrabber
1027 //Now tell the f.g. to get going
1028  m_updated = true;
1029  if(sem_post(&m_smSemaphore) < 0)
1030  {
1031  log<software_critical>({__FILE__, __LINE__, errno, 0, "Error posting to semaphore"});
1032  return -1;
1033  }
1034 
1035 
1036  if(m_averaging)
1037  {
1038  ++m_navg;
1039 
1040  m_avgx1_accum += m_fitter.m_avgx[0];
1041  m_avgx1sq_accum += m_fitter.m_avgx[0]*m_fitter.m_avgx[0];
1042 
1043  m_avgy1_accum += m_fitter.m_avgy[0];
1044  m_avgy1sq_accum += m_fitter.m_avgy[0]*m_fitter.m_avgy[0];
1045 
1046  m_avgD1_accum += 2*m_fitter.m_avgr[0];
1047  m_avgD1sq_accum += 4*m_fitter.m_avgr[0]*m_fitter.m_avgr[0];
1048 
1049  m_avgmed1_accum += m_fitter.m_med[0];
1050  m_avgmed1sq_accum += m_fitter.m_med[0]*m_fitter.m_med[0];
1051 
1054 
1057 
1060 
1063 
1064  m_avgx2_accum += m_fitter.m_avgx[1];
1065  m_avgx2sq_accum += m_fitter.m_avgx[1]*m_fitter.m_avgx[1];
1066 
1067  m_avgy2_accum += m_fitter.m_avgy[1];
1068  m_avgy2sq_accum += m_fitter.m_avgy[1]*m_fitter.m_avgy[1];
1069 
1070  m_avgD2_accum += 2*m_fitter.m_avgr[1];
1071  m_avgD2sq_accum += 4*m_fitter.m_avgr[1]*m_fitter.m_avgr[1];
1072 
1073  m_avgmed2_accum += m_fitter.m_med[1];
1074  m_avgmed2sq_accum += m_fitter.m_med[1]*m_fitter.m_med[1];
1075 
1078 
1081 
1084 
1087 
1088 
1089 
1090  m_avgx3_accum += m_fitter.m_avgx[2];
1091  m_avgx3sq_accum += m_fitter.m_avgx[2]*m_fitter.m_avgx[2];
1092 
1093  m_avgy3_accum += m_fitter.m_avgy[2];
1094  m_avgy3sq_accum += m_fitter.m_avgy[2]*m_fitter.m_avgy[2];
1095 
1096  m_avgD3_accum += 2*m_fitter.m_avgr[2];
1097  m_avgD3sq_accum += 4*m_fitter.m_avgr[2]*m_fitter.m_avgr[2];
1098 
1099  m_avgmed3_accum += m_fitter.m_med[2];
1100  m_avgmed3sq_accum += m_fitter.m_med[2]*m_fitter.m_med[2];
1101 
1104 
1107 
1110 
1113 
1114  if(m_numPupils == 3)
1115  {
1116  double tmp = 0.333*(m_fitter.m_avgx[0]+m_fitter.m_avgx[1]+m_fitter.m_avgx[2]+m_fitter.m_avgx[3]);
1117  m_avgxAll_accum += tmp;
1118  m_avgxAllsq_accum += tmp*tmp;
1119 
1120  tmp = 0.333*(m_fitter.m_avgy[0]+m_fitter.m_avgy[1]+m_fitter.m_avgy[2]);
1121  m_avgyAll_accum += tmp;
1122  m_avgyAllsq_accum += tmp*tmp;
1123 
1124  tmp = 2*0.333*(m_fitter.m_avgr[0]+m_fitter.m_avgr[1]+m_fitter.m_avgr[2]);
1125  m_avgDAll_accum += tmp;
1126  m_avgDAllsq_accum += tmp*tmp;
1127 
1128  tmp = 0.333*(m_fitter.m_med[0]+m_fitter.m_med[1]+m_fitter.m_med[2]);
1129  m_avgmedAll_accum += tmp;
1130  m_avgmedAllsq_accum += tmp*tmp;
1131 
1134 
1137 
1140 
1143 
1144 
1145  std::cerr << "****************************************************************\n";
1146  std::cerr << "Averaged: " << m_navg << "\n";
1147  std::cerr << "Average x1: " << m_avgx1 << " +/- " << sqrt(m_varx1) << "\n";
1148  std::cerr << "Average y1: " << m_avgy1 << " +/- " << sqrt(m_vary1) << "\n";
1149  std::cerr << "Average D1: " << m_avgD1 << " +/- " << sqrt(m_varD1) << "\n";
1150  std::cerr << "Average med1: " << m_avgmed1 << " +/- " << sqrt(m_varmed1) << "\n\n";
1151  std::cerr << "Average x2: " << m_avgx2 << " +/- " << sqrt(m_varx2) << "\n";
1152  std::cerr << "Average y2: " << m_avgy2 << " +/- " << sqrt(m_vary2) << "\n";
1153  std::cerr << "Average D2: " << m_avgD2 << " +/- " << sqrt(m_varD2) << "\n";
1154  std::cerr << "Average med2: " << m_avgmed2 << " +/- " << sqrt(m_varmed2) << "\n\n";
1155  std::cerr << "Average x3: " << m_avgx3 << " +/- " << sqrt(m_varx3) << "\n";
1156  std::cerr << "Average y3: " << m_avgy3 << " +/- " << sqrt(m_vary3) << "\n";
1157  std::cerr << "Average D3: " << m_avgD3 << " +/- " << sqrt(m_varD3) << "\n";
1158  std::cerr << "Average med3: " << m_avgmed3 << " +/- " << sqrt(m_varmed3) << "\n\n";
1159  std::cerr << "Average xAll: " << m_avgxAll << " +/- " << sqrt(m_varxAll) << "\n";
1160  std::cerr << "Average yAll: " << m_avgyAll << " +/- " << sqrt(m_varyAll) << "\n";
1161  std::cerr << "Average DAll: " << m_avgDAll << " +/- " << sqrt(m_varDAll) << "\n";
1162  std::cerr << "Average medAll: " << m_avgmedAll << " +/- " << sqrt(m_varmedAll) << "\n\n";
1163  }
1164  else
1165  {
1166  m_avgx4_accum += m_fitter.m_avgx[3];
1167  m_avgx4sq_accum += m_fitter.m_avgx[3]*m_fitter.m_avgx[3];
1168 
1169  m_avgy4_accum += m_fitter.m_avgy[3];
1170  m_avgy4sq_accum += m_fitter.m_avgy[3]*m_fitter.m_avgy[3];
1171 
1172  m_avgD4_accum += 2*m_fitter.m_avgr[3];
1173  m_avgD4sq_accum += 4*m_fitter.m_avgr[3]*m_fitter.m_avgr[3];
1174 
1175  m_avgmed4_accum += m_fitter.m_med[3];
1176  m_avgmed4sq_accum += m_fitter.m_med[3]*m_fitter.m_med[3];
1177 
1180 
1183 
1186 
1189 
1190 
1191  double tmp = 0.25*(m_fitter.m_avgx[0]+m_fitter.m_avgx[1]+m_fitter.m_avgx[2]+m_fitter.m_avgx[3]);
1192  m_avgxAll_accum += tmp;
1193  m_avgxAllsq_accum += tmp*tmp;
1194 
1195  tmp = 0.25*(m_fitter.m_avgy[0]+m_fitter.m_avgy[1]+m_fitter.m_avgy[2]+m_fitter.m_avgy[3]);
1196  m_avgyAll_accum += tmp;
1197  m_avgyAllsq_accum += tmp*tmp;
1198 
1199  tmp = 2*0.25*(m_fitter.m_avgr[0]+m_fitter.m_avgr[1]+m_fitter.m_avgr[2]+m_fitter.m_avgr[3]);
1200  m_avgDAll_accum += tmp;
1201  m_avgDAllsq_accum += tmp*tmp;
1202 
1203  tmp = 0.25*(m_fitter.m_med[0]+m_fitter.m_med[1]+m_fitter.m_med[2]+m_fitter.m_med[3]);
1204  m_avgmedAll_accum += tmp;
1205  m_avgmedAllsq_accum += tmp*tmp;
1206 
1209 
1212 
1215 
1218 
1219 
1220  std::cerr << "****************************************************************\n";
1221  std::cerr << "Averaged: " << m_navg << "\n";
1222  std::cerr << "Average x1: " << m_avgx1 << " +/- " << sqrt(m_varx1) << "\n";
1223  std::cerr << "Average y1: " << m_avgy1 << " +/- " << sqrt(m_vary1) << "\n";
1224  std::cerr << "Average D1: " << m_avgD1 << " +/- " << sqrt(m_varD1) << "\n";
1225  std::cerr << "Average med1: " << m_avgmed1 << " +/- " << sqrt(m_varmed1) << "\n\n";
1226  std::cerr << "Average x2: " << m_avgx2 << " +/- " << sqrt(m_varx2) << "\n";
1227  std::cerr << "Average y2: " << m_avgy2 << " +/- " << sqrt(m_vary2) << "\n";
1228  std::cerr << "Average D2: " << m_avgD2 << " +/- " << sqrt(m_varD2) << "\n";
1229  std::cerr << "Average med2: " << m_avgmed2 << " +/- " << sqrt(m_varmed2) << "\n\n";
1230  std::cerr << "Average x3: " << m_avgx3 << " +/- " << sqrt(m_varx3) << "\n";
1231  std::cerr << "Average y3: " << m_avgy3 << " +/- " << sqrt(m_vary3) << "\n";
1232  std::cerr << "Average D3: " << m_avgD3 << " +/- " << sqrt(m_varD3) << "\n";
1233  std::cerr << "Average med3: " << m_avgmed3 << " +/- " << sqrt(m_varmed3) << "\n\n";
1234  std::cerr << "Average x4: " << m_avgx4 << " +/- " << sqrt(m_varx4) << "\n";
1235  std::cerr << "Average y4: " << m_avgy4 << " +/- " << sqrt(m_vary4) << "\n";
1236  std::cerr << "Average D4: " << m_avgD4 << " +/- " << sqrt(m_varD4) << "\n";
1237  std::cerr << "Average med4: " << m_avgmed4 << " +/- " << sqrt(m_varmed4) << "\n\n";
1238  std::cerr << "Average xAll: " << m_avgxAll << " +/- " << sqrt(m_varxAll) << "\n";
1239  std::cerr << "Average yAll: " << m_avgyAll << " +/- " << sqrt(m_varyAll) << "\n";
1240  std::cerr << "Average DAll: " << m_avgDAll << " +/- " << sqrt(m_varDAll) << "\n";
1241  std::cerr << "Average medAll: " << m_avgmedAll << " +/- " << sqrt(m_varmedAll) << "\n\n";
1242  }
1243  }
1244 
1245  m_threshShmim.md->write=1;
1246  m_edgeShmim.md->write=1;
1247 
1248  clock_gettime(CLOCK_REALTIME, &m_threshShmim.md->writetime);
1249  m_edgeShmim.md->writetime = m_threshShmim.md->writetime;
1250 
1251  m_threshShmim.md->atime = m_threshShmim.md->writetime;
1252  m_edgeShmim.md->atime = m_threshShmim.md->writetime;
1253 
1254  m_threshShmim.md->cnt0++;
1255  m_edgeShmim.md->cnt0++;
1256 
1257  memcpy(m_threshShmim.array.raw, m_fitIm.data(), m_fitIm.rows()*m_fitIm.cols()*sizeof(float));
1258  memcpy(m_edgeShmim.array.raw, m_edgeIm.data(), m_edgeIm.rows()*m_edgeIm.cols()*sizeof(float));
1259 
1260  m_threshShmim.md->write=0;
1261  m_edgeShmim.md->write=0;
1262 
1263  ImageStreamIO_sempost(&m_threshShmim,-1);
1264  ImageStreamIO_sempost(&m_edgeShmim,-1);
1265 
1266  return 0;
1267 }
1268 
1269 inline
1270 int pupilFit::allocate(const refShmimT & dummy)
1271 {
1272  static_cast<void>(dummy);
1273 
1274  std::lock_guard<std::mutex> guard(m_indiMutex);
1275 
1277  {
1278  return log<software_error,-1>({__FILE__, __LINE__, "reference is not float"});
1279  }
1280 
1282 
1283  return 0;
1284 }
1285 
1286 inline
1287 int pupilFit::processImage( void* curr_src,
1288  const refShmimT & dummy
1289  )
1290 {
1291  static_cast<void>(dummy);
1292 
1293  int npix = 0;
1294  for(unsigned nn=0; nn < refShmimMonitorT::m_width*refShmimMonitorT::m_height; ++nn)
1295  {
1296  m_refIm.data()[nn] = ((float*)curr_src) [nn];
1297  ++npix;
1298  }
1299 
1300  log<text_log>("reference updated", logPrio::LOG_NOTICE);
1301 
1302  std::cerr << m_refIm.sum() << " " << npix << "\n";
1303 
1304  shmimMonitorT::m_restart = true;
1305 
1306  return 0;
1307 }
1308 
1309 inline
1311 {
1312  std::unique_lock<std::mutex> lock(m_indiMutex);
1313 
1316  frameGrabberT::m_dataType = _DATATYPE_FLOAT;
1317 
1318  return 0;
1319 }
1320 
1321 inline
1323 {
1324  return 0;
1325 }
1326 
1327 inline
1329 {
1330  timespec ts;
1331 
1332  if(clock_gettime(CLOCK_REALTIME, &ts) < 0)
1333  {
1334  log<software_critical>({__FILE__,__LINE__,errno,0,"clock_gettime"});
1335  return -1;
1336  }
1337 
1338  ts.tv_sec += 1;
1339 
1340  if(sem_timedwait(&m_smSemaphore, &ts) == 0)
1341  {
1342  if( m_updated )
1343  {
1344  clock_gettime(CLOCK_REALTIME, &m_currImageTimestamp);
1345  return 0;
1346  }
1347  else
1348  {
1349  return 1;
1350  }
1351  }
1352  else
1353  {
1354  return 1;
1355  }
1356 }
1357 
1358 inline
1360 {
1361  ((float *) dest)[0] = m_avg_dx;
1362  ((float *) dest)[1] = m_avg_dy;
1363 
1364  m_updated = false;
1365  return 0;
1366 }
1367 
1368 inline
1370 {
1371  return 0;
1372 }
1373 
1374 INDI_NEWCALLBACK_DEFN(pupilFit, m_indiP_thresh)(const pcf::IndiProperty & ipRecv)
1375 {
1376  if(ipRecv.getName() != m_indiP_thresh.getName())
1377  {
1378  log<software_error>({__FILE__,__LINE__, "wrong INDI property received."});
1379  return -1;
1380  }
1381 
1382  float target;
1383 
1384  if( indiTargetUpdate( m_indiP_thresh, target, ipRecv, true) < 0)
1385  {
1386  log<software_error>({__FILE__,__LINE__});
1387  return -1;
1388  }
1389 
1390  m_threshold = target;
1391 
1392  if(m_setPointSource == USEREFIM) shmimMonitorT::m_restart = true; //need to re-process the reference
1393 
1394  log<text_log>("set threshold = " + std::to_string(m_threshold), logPrio::LOG_NOTICE);
1395  return 0;
1396 }
1397 
1398 INDI_NEWCALLBACK_DEFN(pupilFit, m_indiP_averaging)(const pcf::IndiProperty & ipRecv)
1399 {
1400  if(ipRecv.getName() != m_indiP_averaging.getName())
1401  {
1402  log<software_error>({__FILE__,__LINE__, "wrong INDI property received."});
1403  return -1;
1404  }
1405 
1406  if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On)
1407  {
1408 
1409  m_avgx1_accum = 0;
1410  m_avgx1sq_accum = 0;
1411  m_avgy1_accum = 0;
1412  m_avgy1sq_accum = 0;
1413  m_avgD1_accum = 0;
1414  m_avgD1sq_accum = 0;
1415  m_avgmed1_accum = 0;
1416  m_avgmed1sq_accum = 0;
1417 
1418  m_avgx2_accum = 0;
1419  m_avgx2sq_accum = 0;
1420  m_avgy2_accum = 0;
1421  m_avgy2sq_accum = 0;
1422  m_avgD2_accum = 0;
1423  m_avgD2sq_accum = 0;
1424  m_avgmed2_accum = 0;
1425  m_avgmed2sq_accum = 0;
1426 
1427  m_avgx3_accum = 0;
1428  m_avgx3sq_accum = 0;
1429  m_avgy3_accum = 0;
1430  m_avgy3sq_accum = 0;
1431  m_avgD3_accum = 0;
1432  m_avgD3sq_accum = 0;
1433  m_avgmed3_accum = 0;
1434  m_avgmed3sq_accum = 0;
1435 
1436  m_avgx4_accum = 0;
1437  m_avgx4sq_accum = 0;
1438  m_avgy4_accum = 0;
1439  m_avgy4sq_accum = 0;
1440  m_avgD4_accum = 0;
1441  m_avgD4sq_accum = 0;
1442  m_avgmed4_accum = 0;
1443  m_avgmed4sq_accum = 0;
1444 
1445  m_avgxAll_accum = 0;
1446  m_avgxAllsq_accum = 0;
1447  m_avgyAll_accum = 0;
1448  m_avgyAllsq_accum = 0;
1449  m_avgDAll_accum = 0;
1450  m_avgDAllsq_accum = 0;
1451  m_avgmedAll_accum = 0;
1452  m_avgmedAllsq_accum = 0;
1453 
1454  m_navg = 0;
1455  m_averaging = true;
1456 
1457  updateSwitchIfChanged(m_indiP_averaging, "toggle", pcf::IndiElement::On, INDI_BUSY);
1458 
1459  log<text_log>("began averaging");
1460 
1461  }
1462  else if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::Off)
1463  {
1464  m_averaging = false;
1465  updateSwitchIfChanged(m_indiP_averaging, "toggle", pcf::IndiElement::Off, INDI_IDLE);
1466 
1467  log<text_log>("stopped averaging");
1468  }
1469 
1470  return 0;
1471 }
1472 
1473 INDI_NEWCALLBACK_DEFN(pupilFit, m_indiP_reload)(const pcf::IndiProperty & ipRecv)
1474 {
1475  if(ipRecv.getName() != m_indiP_reload.getName())
1476  {
1477  log<software_error>({__FILE__,__LINE__, "wrong INDI property received."});
1478  return -1;
1479  }
1480 
1481  if( ipRecv["request"].getSwitchState() == pcf::IndiElement::On)
1482  {
1483  log<text_log>("reloading");
1484  shmimMonitorT::m_restart = 1;
1485  }
1486 
1487  return 0;
1488 }
1489 
1490 INDI_NEWCALLBACK_DEFN(pupilFit, m_indiP_update)(const pcf::IndiProperty & ipRecv)
1491 {
1492  if(ipRecv.getName() != m_indiP_update.getName())
1493  {
1494  log<software_error>({__FILE__,__LINE__, "wrong INDI property received."});
1495  return -1;
1496  }
1497 
1498  if( ipRecv["request"].getSwitchState() == pcf::IndiElement::On)
1499  {
1500  std::lock_guard<std::mutex> guard(m_indiMutex);
1501 
1502  m_setx1 = m_indiP_quad1["x"].get<float>();
1503  m_sety1 = m_indiP_quad1["y"].get<float>();
1504  m_setD1 = m_indiP_quad1["D"].get<float>();
1505 
1506  m_setx2 = m_indiP_quad2["x"].get<float>();
1507  m_sety2 = m_indiP_quad2["y"].get<float>();
1508  m_setD2 = m_indiP_quad2["D"].get<float>();
1509 
1510  m_setx3 = m_indiP_quad3["x"].get<float>();
1511  m_sety3 = m_indiP_quad3["y"].get<float>();
1512  m_setD3 = m_indiP_quad3["D"].get<float>();
1513 
1514  log<text_log>("Recorded current set-points: ");
1515  log<text_log>("Quad 1 set points: " + std::to_string(m_setx1) + " " + std::to_string(m_sety1) + " " + std::to_string(m_setD1));
1516  log<text_log>("Quad 2 set points: " + std::to_string(m_setx2) + " " + std::to_string(m_sety2) + " " + std::to_string(m_setD2));
1517  log<text_log>("Quad 3 set points: " + std::to_string(m_setx3) + " " + std::to_string(m_sety3) + " " + std::to_string(m_setD3));
1518 
1519  if(m_numPupils == 4)
1520  {
1521  m_setx4 = m_indiP_quad4["x"].get<float>();
1522  m_sety4 = m_indiP_quad4["y"].get<float>();
1523  m_setD4 = m_indiP_quad4["D"].get<float>();
1524  log<text_log>("Quad 4 set points: " + std::to_string(m_setx4) + " " + std::to_string(m_sety4) + " " + std::to_string(m_setD4));
1525  }
1526 
1527  if(m_setPointSource == USEUSERSET) shmimMonitorT::m_restart = true;
1528  }
1529 
1530  return 0;
1531 }
1532 
1533 INDI_NEWCALLBACK_DEFN(pupilFit, m_indiP_refmode)(const pcf::IndiProperty & ipRecv)
1534 {
1535  if(ipRecv.getName() != m_indiP_refmode.getName())
1536  {
1537  log<software_error>({__FILE__,__LINE__, "wrong INDI property received."});
1538  return -1;
1539  }
1540 
1541  if(ipRecv.find("default"))
1542  {
1543  if( ipRecv["default"].getSwitchState() == pcf::IndiElement::On)
1544  {
1545  if( m_setPointSource != USEDEFSET)
1546  {
1547  log<text_log>("using default reference.", logPrio::LOG_NOTICE);
1548  m_setPointSource = USEDEFSET;
1549  shmimMonitorT::m_restart = true;
1550  return 0;
1551  }
1552  }
1553  }
1554  if(ipRecv.find("refim"))
1555  {
1556  if( ipRecv["refim"].getSwitchState() == pcf::IndiElement::On)
1557  {
1558  if( m_setPointSource != USEREFIM)
1559  {
1560  log<text_log>("using reference image.", logPrio::LOG_NOTICE);
1561  m_setPointSource = USEREFIM;
1562  shmimMonitorT::m_restart = true;
1563  return 0;
1564  }
1565  }
1566  }
1567  if(ipRecv.find("user"))
1568  {
1569  if( ipRecv["user"].getSwitchState() == pcf::IndiElement::On)
1570  {
1571  if( m_setPointSource != USEUSERSET)
1572  {
1573  log<text_log>("using user image.", logPrio::LOG_NOTICE);
1574  m_setPointSource = USEUSERSET;
1575  shmimMonitorT::m_restart = true;
1576  return 0;
1577  }
1578  }
1579  }
1580 
1581  return 0;
1582 }
1583 
1584 inline
1586 {
1588 }
1589 
1590 inline
1592 {
1593  return recordFGTimings(true);
1594 }
1595 
1596 } //namespace app
1597 } //namespace MagAOX
1598 
1599 #endif //pupilFit_hpp
#define IMAGESTRUCT_FLOAT
Definition: ImageStruct.hpp:22
The base-class for MagAO-X applications.
Definition: MagAOXApp.hpp:73
void updateIfChanged(pcf::IndiProperty &p, const std::string &el, const T &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI property element value if it has changed.
Definition: MagAOXApp.hpp:3120
int createStandardIndiRequestSw(pcf::IndiProperty &prop, const std::string &name, const std::string &label="", const std::string &group="")
Create a standard R/W INDI switch with a single request element.
Definition: MagAOXApp.hpp:2573
stateCodes::stateCodeT state()
Get the current state code.
Definition: MagAOXApp.hpp:2297
int registerIndiPropertyNew(pcf::IndiProperty &prop, int(*)(void *, const pcf::IndiProperty &))
Register an INDI property which is exposed for others to request a New Property for.
int createStandardIndiToggleSw(pcf::IndiProperty &prop, const std::string &name, const std::string &label="", const std::string &group="")
Create a standard R/W INDI switch with a single toggle element.
Definition: MagAOXApp.hpp:2543
indiDriver< MagAOXApp > * m_indiDriver
The INDI driver wrapper. Constructed and initialized by execute, which starts and stops communication...
Definition: MagAOXApp.hpp:542
void updateSwitchIfChanged(pcf::IndiProperty &p, const std::string &el, const pcf::IndiElement::SwitchStateType &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI switch element value if it has changed.
Definition: MagAOXApp.hpp:3144
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
Definition: MagAOXApp.hpp:1804
int createROIndiNumber(pcf::IndiProperty &prop, const std::string &propName, const std::string &propLabel="", const std::string &propGroup="")
Create a ReadOnly INDI Number property.
Definition: MagAOXApp.hpp:2517
int registerIndiPropertyReadOnly(pcf::IndiProperty &prop)
Register an INDI property which is read only.
Definition: MagAOXApp.hpp:2655
std::mutex m_indiMutex
Mutex for locking INDI communications.
Definition: MagAOXApp.hpp:545
int createStandardIndiSelectionSw(pcf::IndiProperty &prop, const std::string &name, const std::vector< std::string > &elements, const std::vector< std::string > &elementLabels, const std::string &label="", const std::string &group="")
Create a standard R/W INDI selection (one of many) switch with vector of elements and element labels.
Definition: MagAOXApp.hpp:2603
timespec m_currImageTimestamp
The timestamp of the current image.
uint32_t m_width
The width of the image, once deinterlaced etc.
int appShutdown()
Shuts down the framegrabber thread.
int loadConfig(mx::app::appConfigurator &config)
load the configuration system results
int updateINDI()
Update the INDI properties for this device controller.
uint8_t m_dataType
The ImageStreamIO type code.
int appLogic()
Checks the framegrabber thread.
uint32_t m_height
The height of the image, once deinterlaced etc.
int setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
uint32_t m_width
The width of the images in the stream.
int setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
int updateINDI()
Update the INDI properties for this device controller.
int appLogic()
Checks the shmimMonitor thread.
uint32_t m_height
The height of the images in the stream.
std::string m_shmimName
The name of the shared memory image, is used in /tmp/<shmimName>.im.shm. Derived classes should set a...
int appShutdown()
Shuts down the shmimMonitor thread.
uint8_t m_dataType
The ImageStreamIO type code.
bool m_restart
Flag indicating tha the shared memory should be reinitialized.
int loadConfig(mx::app::appConfigurator &config)
load the configuration system results
bool m_getExistingFirst
If set to true by derivedT, any existing image will be grabbed and sent to processImage before waitin...
The MagAO-X Pyramid Pupil Fitter.
Definition: pupilFit.hpp:55
virtual int appShutdown()
Shutdown the app.
Definition: pupilFit.hpp:776
~pupilFit() noexcept
D'tor, declared and defined for noexcept.
Definition: pupilFit.hpp:452
pcf::IndiProperty m_indiP_quad1
Definition: pupilFit.hpp:415
pcf::IndiProperty m_indiP_numPupils
Definition: pupilFit.hpp:413
pcf::IndiProperty m_indiP_quad2
Definition: pupilFit.hpp:416
mx::improc::eigenImage< float > m_fitIm
Definition: pupilFit.hpp:103
INDI_NEWCALLBACK_DECL(pupilFit, m_indiP_refmode)
int m_numPupils
The number of pupils. Default is 4. 3 is also supported.
Definition: pupilFit.hpp:99
friend class pupilFit_test
Definition: pupilFit.hpp:57
pcf::IndiProperty m_indiP_refmode
Definition: pupilFit.hpp:428
INDI_NEWCALLBACK_DECL(pupilFit, m_indiP_update)
std::string m_edgeShmimName
The name of the image stream for the edge images. Default is camwfs_edge.
Definition: pupilFit.hpp:95
mx::improc::eigenImage< float > m_refIm
Definition: pupilFit.hpp:102
int processImage(void *curr_src, const dev::shmimT &)
Definition: pupilFit.hpp:919
INDI_NEWCALLBACK_DECL(pupilFit, m_indiP_thresh)
dev::shmimMonitor< pupilFit, refShmimT > refShmimMonitorT
Definition: pupilFit.hpp:69
dev::shmimMonitor< pupilFit > shmimMonitorT
Definition: pupilFit.hpp:67
virtual int appLogic()
Implementation of the FSM for pupilFit.
Definition: pupilFit.hpp:719
int loadImageIntoStream(void *dest)
Implementation of the framegrabber loadImageIntoStream interface.
Definition: pupilFit.hpp:1359
static constexpr bool c_frameGrabber_flippable
app:dev config to tell framegrabber these images can not be flipped
Definition: pupilFit.hpp:84
float realT
Floating point type in which to do all calculations.
Definition: pupilFit.hpp:78
int startAcquisition()
Implementation of the framegrabber startAcquisition interface.
Definition: pupilFit.hpp:1322
pcf::IndiProperty m_indiP_quad3
Definition: pupilFit.hpp:417
virtual int appStartup()
Startup function.
Definition: pupilFit.hpp:544
pcf::IndiProperty m_indiP_averaging
Definition: pupilFit.hpp:410
INDI_NEWCALLBACK_DECL(pupilFit, m_indiP_reload)
virtual void loadConfig()
Definition: pupilFit.hpp:538
dev::frameGrabber< pupilFit > frameGrabberT
Definition: pupilFit.hpp:72
pcf::IndiProperty m_indiP_avg
Definition: pupilFit.hpp:420
pupilFitter< realT > m_fitter
Definition: pupilFit.hpp:106
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
Definition: pupilFit.hpp:501
pcf::IndiProperty m_indiP_thresh
Definition: pupilFit.hpp:406
pcf::IndiProperty m_indiP_reload
Definition: pupilFit.hpp:422
pcf::IndiProperty m_indiP_quad4
Definition: pupilFit.hpp:418
dev::telemeter< pupilFit > telemeterT
Definition: pupilFit.hpp:75
int acquireAndCheckValid()
Implementation of the framegrabber acquireAndCheckValid interface.
Definition: pupilFit.hpp:1328
float fps()
Implementation of the framegrabber fps interface.
Definition: pupilFit.hpp:365
int reconfig()
Implementation of the framegrabber reconfig interface.
Definition: pupilFit.hpp:1369
std::string m_threshShmimName
The name of the image stream for the thresholded images. Default is camwfs_thresh.
Definition: pupilFit.hpp:94
pcf::IndiProperty m_indiP_update
Definition: pupilFit.hpp:425
bool m_refUpdated
Flag set if the online reference update is used.
Definition: pupilFit.hpp:148
int allocate(const dev::shmimT &)
Definition: pupilFit.hpp:787
INDI_NEWCALLBACK_DECL(pupilFit, m_indiP_averaging)
sem_t m_smSemaphore
Semaphore used to synchronize the fg thread and the sm thread.
Definition: pupilFit.hpp:345
pupilFit()
Default c'tor.
Definition: pupilFit.hpp:445
virtual void setupConfig()
Definition: pupilFit.hpp:466
int recordTelem(const telem_fgtimings *)
Definition: pupilFit.hpp:1591
int configureAcquisition()
Implementation of the framegrabber configureAcquisition interface.
Definition: pupilFit.hpp:1310
mx::improc::eigenImage< float > m_edgeIm
Definition: pupilFit.hpp:104
#define INDI_NEWCALLBACK(prop)
Get the name of the static callback wrapper for a new property.
Definition: indiMacros.hpp:208
@ OPERATING
The device is operating, other than homing.
Definition: stateCodes.hpp:55
#define INDI_IDLE
Definition: indiUtils.hpp:28
#define INDI_BUSY
Definition: indiUtils.hpp:30
std::ostream & cerr()
void updateSwitchIfChanged(pcf::IndiProperty &p, const std::string &el, const pcf::IndiElement::SwitchStateType &newVal, indiDriverT *indiDriver, pcf::IndiProperty::PropertyStateType newState=pcf::IndiProperty::Ok)
Update the value of the INDI element, but only if it has changed.
Definition: indiUtils.hpp:212
const pcf::IndiProperty & ipRecv
Definition: MagAOXApp.hpp:3434
INDI_NEWCALLBACK_DEFN(acesxeCtrl, m_indiP_windspeed)(const pcf
Definition: acesxeCtrl.hpp:687
std::unique_lock< std::mutex > lock(m_indiMutex)
Definition: dm.hpp:24
constexpr static logPrioT LOG_ERROR
An error has occured which the software will attempt to correct.
Definition: logPriority.hpp:40
constexpr static logPrioT LOG_NOTICE
A normal but significant condition.
Definition: logPriority.hpp:46
#define USEDEFSET
Definition: pupilFit.hpp:46
#define USEREFIM
Definition: pupilFit.hpp:47
#define USEUSERSET
Definition: pupilFit.hpp:48
The MagAO-X Pyramid Pupil Fitter class header.
A device base class which saves telemetry.
Definition: telemeter.hpp:69
int appShutdown()
Perform telemeter application shutdown.
Definition: telemeter.hpp:274
int loadConfig(appConfigurator &config)
Load the device section from an application configurator.
Definition: telemeter.hpp:223
int appLogic()
Perform telemeter application logic.
Definition: telemeter.hpp:268
int setupConfig(appConfigurator &config)
Setup an application configurator for the device section.
Definition: telemeter.hpp:211
int appStartup()
Starts the telemetry log thread.
Definition: telemeter.hpp:241
int checkRecordTimes(const telT &tel, telTs... tels)
Check the time of the last record for each telemetry type and make an entry if needed.
Definition: telemeter.hpp:281
Struct to perform centration and measure diameter of Pyramid pupils.
Definition: pupilFitter.hpp:23
static std::string indiPrefix()
Definition: pupilFit.hpp:40
static std::string configSection()
Definition: pupilFit.hpp:35
Software ERR log entry.
Log entry recording framegrabber timings.