API
pupilAlign.hpp
Go to the documentation of this file.
1 /** \file pupilAlign.hpp
2  * \brief The MagAO-X Pyramid Pupil Alignment application header
3  *
4  * \ingroup pupilAlign_files
5  */
6 
7 #ifndef pupilAlign_hpp
8 #define pupilAlign_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 
14 /** \defgroup pupilAlign
15  * \brief The MagAO-X pyramid pupil aligner.
16  *
17  * <a href="../handbook/operating/software/apps/pupilAlign.html">Application Documentation</a>
18  *
19  * \ingroup apps
20  *
21  */
22 
23 /** \defgroup pupilAlign_files
24  * \ingroup pupilAlign
25  */
26 
27 namespace MagAOX
28 {
29 namespace app
30 {
31 
32 /// The MagAO-X Pyramid Pupil Fitter
33 /**
34  * \ingroup pupilAlign
35  */
36 class pupilAlign : public MagAOXApp<true>, public dev::shmimMonitor<pupilAlign>
37 {
38 
39  //Give the test harness access.
40  friend class pupilAlign_test;
41 
42  friend class dev::shmimMonitor<pupilAlign>;
43 
44  //The base shmimMonitor type
46 
47  ///Floating point type in which to do all calculations.
48  typedef float realT;
49 
51 
52 protected:
53 
54  /** \name Configurable Parameters
55  *@{
56  */
57 
58  std::string m_pupilShmimName; ///< The name of the pupil shared memory image
59 
60  std::string m_darkShmimName; ///< The name of the dark shared memory stream. Default is <m_pupilShmimName>_dark
61 
62  int m_navg {10}; ///< Number of images to average. Default is 10.
63 
64  float m_threshold {300}; ///< The default SNR threshold for finding the pupil
65 
66  ///@}
67 
68  mx::improc::eigenImage<float> m_darkIm;
69  mx::improc::eigenImage<float> m_pupIm;
70  mx::improc::eigenImage<float> m_tgtIm;
71  mx::improc::eigenImage<float> m_tgtPupSubIm;
72 
73  IMAGE m_pupShmim;
74  bool m_pupShmimConnected {false};
75 
76  IMAGE m_tgtShmim;
77  bool m_tgtShmimConnected {false};
78 
79  IMAGE m_tgtShmim;
81 
82  mx::improc::sourceFinder<float> m_srcFind;
83 
84  std::vector<pixelT> srcPos;
85 
86  float m_dmXcen {0};
87 
88  float m_dmYcen {0};
89 
90 
91 public:
92  /// Default c'tor.
93  pupilAlign();
94 
95  /// D'tor, declared and defined for noexcept.
96  ~pupilAlign() noexcept;
97 
98  virtual void setupConfig();
99 
100  /// Implementation of loadConfig logic, separated for testing.
101  /** This is called by loadConfig().
102  */
103  int loadConfigImpl( mx::app::appConfigurator & _config /**< [in] an application configuration from which to load values*/);
104 
105  virtual void loadConfig();
106 
107  /// Startup function
108  /**
109  *
110  */
111  virtual int appStartup();
112 
113  /// Implementation of the FSM for pupilAlign.
114  /**
115  * \returns 0 on no critical error
116  * \returns -1 on an error requiring shutdown
117  */
118  virtual int appLogic();
119 
120  /// Shutdown the app.
121  /**
122  *
123  */
124  virtual int appShutdown();
125 
126  int allocate( const dev::shmimT &);
127 
128  int processImage( void* curr_src,
129  const dev::shmimT &
130  );
131 
132 protected:
133 
134 
135  /** \name INDI
136  * @{
137  */
138 
139  pcf::IndiProperty m_indiP_navg;
140 
142 
143  pcf::IndiProperty m_indiP_threshold;
145 
146  pcf::IndiProperty m_indiP_tgtCoords;
147 
148 
149  pcf::IndiProperty m_indiP_takePupil;
151 
152  pcf::IndiProperty m_indiP_takeTgt;
154 
155  ///@}
156 };
157 
158 inline
159 pupilAlign::pupilAlign() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
160 {
161  return;
162 }
163 
164 inline
166 {
167  if(m_threshShmimConnected)
168  {
169  ImageStreamIO_destroyIm( &m_threshShmim );
170  }
171 
172  if(m_edgeShmimConnected)
173  {
174  ImageStreamIO_destroyIm( &m_edgeShmim );
175  }
176 }
177 
178 inline
180 {
182 
183  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");
184 
185  config.add("fit.threshold", "", "fit.threshold", argType::Required, "fit", "threshold", false, "float", "The pupil finding threshold. 0 < threshold < 1");
186  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.");
187  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.");
188 
189  config.add("fit.numPupils", "", "fit.numPupils", argType::Required, "fit", "numPupils", false, "int", "The number of pupils. Default is 4. 3 is also supported.");
190  config.add("fit.pupMedIndex", "", "fit.pupMedIndex", argType::Required, "fit", "pupMedIndex", false, "float", "The index of the pupil median in a sorted quadrant.");
191 
192  config.add("wfsref.path", "" , "wfsref.path", argType::Required, "wfsref", "path", false, "float", "The path to the WFS reference image. Default is /opt/MagAOX/cacao/tweeter");
193  config.add("wfsref.name", "" , "wfsref.name", argType::Required, "wfsref", "name", false, "float", "The name the WFS reference image. Default is wfsref0.fits");
194 }
195 
196 
197 inline
198 int pupilAlign::loadConfigImpl( mx::app::appConfigurator & _config )
199 {
200  m_shmimName = "camwfs_avg";
201  shmimMonitorT::loadConfig(_config);
202 
203  _config(m_threshold, "fit.threshold");
204  _config(m_threshShmimName, "fit.threshShmimName");
205  _config(m_edgeShmimName, "fit.edgeShmimName");
206  _config(m_numPupils, "fit.numPupils");
207  _config(m_fitter.m_pupMedIndex, "fit.pupMedIndex");
208 
209  _config(m_wfsrefPath, "wfsref.path");
210  _config(m_wfsrefName, "wfsref.name");
211 
212  return 0;
213 }
214 
215 inline
217 {
218  loadConfigImpl(config);
219 }
220 
221 inline
223 {
224  if(shmimMonitorT::appStartup() < 0)
225  {
226  return log<software_error,-1>({__FILE__, __LINE__});
227  }
228 
229  createStandardIndiNumber<float>( m_indiP_thresh, "threshold", 0, 1 ,0, "%0.2f", "Threshold");
230  m_indiP_thresh["current"].set(m_threshold);
231  m_indiP_thresh["target"].set(m_threshold);
232  registerIndiPropertyNew(m_indiP_thresh, INDI_NEWCALLBACK(m_indiP_thresh));
233 
234  createStandardIndiToggleSw( m_indiP_averaging, "averaging", "Start/Stop Averaging");
235  m_indiP_averaging["toggle"].set(pcf::IndiElement::Off);
236  if( registerIndiPropertyNew( m_indiP_averaging, INDI_NEWCALLBACK(m_indiP_averaging)) < 0)
237  {
238  log<software_error>({__FILE__,__LINE__});
239  return -1;
240  }
241 
242  createROIndiNumber( m_indiP_numPupils, "numPupils", "Number of Pupils");
243  indi::addNumberElement<int>( m_indiP_numPupils, "value", 3, 4, 1, "%d", "");
244  m_indiP_numPupils["value"].set(m_numPupils);
245  registerIndiPropertyReadOnly(m_indiP_numPupils);
246 
247  createROIndiNumber( m_indiP_quad1, "quadrant1", "Quadrant 1");
248  indi::addNumberElement<float>( m_indiP_quad1, "x", 0, 59, 0, "%0.2f", "center x");
249  indi::addNumberElement<float>( m_indiP_quad1, "dx", 0, 59, 0, "%0.2f", "delta-x");
250  indi::addNumberElement<float>( m_indiP_quad1, "y", 0, 59, 0, "%0.2f", "center x");
251  indi::addNumberElement<float>( m_indiP_quad1, "dy", 0, 59, 0, "%0.2f", "delta-y");
252  indi::addNumberElement<float>( m_indiP_quad1, "D", 0, 59, 0, "%0.2f", "diameter");
253  indi::addNumberElement<float>( m_indiP_quad1, "dD", 0, 59, 0, "%0.2f", "delta-D");
254  indi::addNumberElement<float>( m_indiP_quad1, "med", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "flux");
255  indi::addNumberElement<float>( m_indiP_quad1, "set-x", 0, 59, 0, "%0.2f", "set pt. center x");
256  m_indiP_quad1["set-x"] = m_setx1;
257  indi::addNumberElement<float>( m_indiP_quad1, "set-y", 0, 59, 0, "%0.2f", "set pt. center x");
258  m_indiP_quad1["set-y"] = m_sety1;
259  indi::addNumberElement<float>( m_indiP_quad1, "set-D", 0, 59, 0, "%0.2f", "set pt. diameter");
260  m_indiP_quad1["set-D"] = m_setD1;
261 
262  registerIndiPropertyReadOnly(m_indiP_quad1);
263 
264  createROIndiNumber( m_indiP_quad2, "quadrant2", "Quadrant 2");
265  indi::addNumberElement<float>( m_indiP_quad2, "x", 0, 59, 0, "%0.2f", "center x");
266  indi::addNumberElement<float>( m_indiP_quad2, "dx", 0, 59, 0, "%0.2f", "delta-x");
267  indi::addNumberElement<float>( m_indiP_quad2, "y", 0, 59, 0, "%0.2f", "center y");
268  indi::addNumberElement<float>( m_indiP_quad2, "dy", 0, 59, 0, "%0.2f", "delta-y");
269  indi::addNumberElement<float>( m_indiP_quad2, "D", 0, 59, 0, "%0.2f", "diameter");
270  indi::addNumberElement<float>( m_indiP_quad2, "dD", 0, 59, 0, "%0.2f", "delta-D");
271  indi::addNumberElement<float>( m_indiP_quad2, "med", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "flux");
272  indi::addNumberElement<float>( m_indiP_quad2, "set-x", 0, 59, 0, "%0.2f", "set pt. center x");
273  m_indiP_quad2["set-x"] = m_setx2;
274  indi::addNumberElement<float>( m_indiP_quad2, "set-y", 0, 59, 0, "%0.2f", "set pt. center x");
275  m_indiP_quad2["set-y"] = m_sety2;
276  indi::addNumberElement<float>( m_indiP_quad2, "set-D", 0, 59, 0, "%0.2f", "set pt. diameter");
277  m_indiP_quad2["set-D"] = m_setD2;
278  registerIndiPropertyReadOnly(m_indiP_quad2);
279 
280  createROIndiNumber( m_indiP_quad3, "quadrant3", "Quadrant 3");
281  indi::addNumberElement<float>( m_indiP_quad3, "x", 0, 59, 0, "%0.2f", "center x");
282  indi::addNumberElement<float>( m_indiP_quad3, "dx", 0, 59, 0, "%0.2f", "delta-x");
283  indi::addNumberElement<float>( m_indiP_quad3, "y", 0, 59, 0, "%0.2f", "center y");
284  indi::addNumberElement<float>( m_indiP_quad3, "dy", 0, 59, 0, "%0.2f", "delta-y");
285  indi::addNumberElement<float>( m_indiP_quad3, "D", 0, 59, 0, "%0.2f", "diameter");
286  indi::addNumberElement<float>( m_indiP_quad3, "dD", 0, 59, 0, "%0.2f", "delta-D");
287  indi::addNumberElement<float>( m_indiP_quad3, "med", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "flux");
288  indi::addNumberElement<float>( m_indiP_quad3, "set-x", 0, 59, 0, "%0.2f", "set pt. center x");
289  m_indiP_quad3["set-x"] = m_setx3;
290  indi::addNumberElement<float>( m_indiP_quad3, "set-y", 0, 59, 0, "%0.2f", "set pt. center x");
291  m_indiP_quad3["set-y"] = m_sety3;
292  indi::addNumberElement<float>( m_indiP_quad3, "set-D", 0, 59, 0, "%0.2f", "set pt. diameter");
293  m_indiP_quad3["set-D"] = m_setD3;
294  registerIndiPropertyReadOnly(m_indiP_quad3);
295 
296  if(m_numPupils != 3)
297  {
298  createROIndiNumber( m_indiP_quad4, "quadrant4", "Quadrant 4");
299  indi::addNumberElement<float>( m_indiP_quad4, "x", 0, 59, 0, "%0.2f", "center x");
300  indi::addNumberElement<float>( m_indiP_quad4, "dx", 0, 59, 0, "%0.2f", "delta-x");
301  indi::addNumberElement<float>( m_indiP_quad4, "y", 0, 59, 0, "%0.2f", "center y");
302  indi::addNumberElement<float>( m_indiP_quad4, "dy", 0, 59, 0, "%0.2f", "delta-y");
303  indi::addNumberElement<float>( m_indiP_quad4, "D", 0, 59, 0, "%0.2f", "diameter");
304  indi::addNumberElement<float>( m_indiP_quad4, "dD", 0, 59, 0, "%0.2f", "delta-D");
305  indi::addNumberElement<float>( m_indiP_quad4, "med", 0, std::numeric_limits<uint16_t>::max(), 0, "%0.1f", "flux");
306  indi::addNumberElement<float>( m_indiP_quad4, "set-x", 0, 59, 0, "%0.2f", "set pt. center x");
307  m_indiP_quad4["set-x"] = m_setx4;
308  indi::addNumberElement<float>( m_indiP_quad4, "set-y", 0, 59, 0, "%0.2f", "set pt. center x");
309  m_indiP_quad4["set-y"] = m_sety4;
310  indi::addNumberElement<float>( m_indiP_quad4, "set-D", 0, 59, 0, "%0.2f", "set pt. diameter");
311  m_indiP_quad4["set-D"] = m_setD4;
312  registerIndiPropertyReadOnly(m_indiP_quad4);
313  }
314 
315  createROIndiNumber( m_indiP_avg, "average", "Average");
316  indi::addNumberElement<float>( m_indiP_avg, "x", 0, 59, 0, "%0.2f", "center x");
317  indi::addNumberElement<float>( m_indiP_avg, "dx", 0, 59, 0, "%0.2f", "delta-x");
318  indi::addNumberElement<float>( m_indiP_avg, "y", 0, 59, 0, "%0.2f", "center y");
319  indi::addNumberElement<float>( m_indiP_avg, "dy", 0, 59, 0, "%0.2f", "delta-y");
320  indi::addNumberElement<float>( m_indiP_avg, "D", 0, 59, 0, "%0.2f", "diameter");
321  indi::addNumberElement<float>( m_indiP_avg, "dD", 0, 59, 0, "%0.2f", "delta-D");
322  registerIndiPropertyReadOnly(m_indiP_avg);
323 
324  createStandardIndiRequestSw( m_indiP_reload, "reload", "Reload Calibration");
325  m_indiP_reload["request"].set(pcf::IndiElement::Off);
326  if( registerIndiPropertyNew( m_indiP_reload, INDI_NEWCALLBACK(m_indiP_reload)) < 0)
327  {
328  log<software_error>({__FILE__,__LINE__});
329  return -1;
330  }
331 
332  createStandardIndiRequestSw( m_indiP_update, "update_ref", "Update Reference");
333  m_indiP_update["request"].set(pcf::IndiElement::Off);
334  if( registerIndiPropertyNew( m_indiP_update, INDI_NEWCALLBACK(m_indiP_update)) < 0)
335  {
336  log<software_error>({__FILE__,__LINE__});
337  return -1;
338  }
340 
341  return 0;
342 }
343 
344 inline
346 {
347  if( shmimMonitorT::appLogic() < 0)
348  {
349  return log<software_error,-1>({__FILE__,__LINE__});
350  }
351 
352  std::lock_guard<std::mutex> guard(m_indiMutex);
353  updateIfChanged(m_indiP_thresh, "current", m_threshold, INDI_IDLE);
354  updateIfChanged(m_indiP_thresh, "target", m_threshold, INDI_IDLE);
355 
357 
358  return 0;
359 }
360 
361 inline
363 {
365 
366  return 0;
367 }
368 
369 inline
371 {
372  static_cast<void>(dummy);
373 
374  m_fitIm.resize(m_width, m_height);
375  m_edgeIm.resize(m_width, m_height);
376 
377  m_fitter.m_numPupils = m_numPupils;
378  m_fitter.setSize(0.5*m_width, 0.5*m_height);
379  m_fitter.m_thresh = m_threshold;
380 
381  //Load and fit the reference image
382  std::string reffits = m_wfsrefPath + "/" + m_wfsrefName;
383 
384  mx::fits::fitsFile<float> ff;
385  mx::improc::eigenImage<float> refedge;
386 
387  ff.read(m_refIm, reffits);
388 
389  if(m_useRefIm)
390  {
391  if(m_refIm.rows() == m_width && m_refIm.cols() == m_height)
392  {
393  if(m_fitter.fit(m_refIm, refedge) < 0)
394  {
395  log<software_error>({__FILE__, __LINE__, "error from fitter"});
396  }
397  else
398  {
399  m_setx1 = m_fitter.m_avgx[0];
400  m_sety1 = m_fitter.m_avgy[0];
401  m_setD1 = 2*m_fitter.m_avgr[0];
402 
403  m_setx2 = m_fitter.m_avgx[1];
404  m_sety2 = m_fitter.m_avgy[1];
405  m_setD2 = 2*m_fitter.m_avgr[1];
406 
407  m_setx3 = m_fitter.m_avgx[2];
408  m_sety3 = m_fitter.m_avgy[2];
409  m_setD3 = 2*m_fitter.m_avgr[2];
410 
411  m_setx4 = m_fitter.m_avgx[3];
412  m_sety4 = m_fitter.m_avgy[3];
413  m_setD4 = 2*m_fitter.m_avgr[3];
414 
415  log<text_log>("Read reference image: " + reffits);
416  log<text_log>("Quad 1 set points: " + std::to_string(m_setx1) + " " + std::to_string(m_sety1) + " " + std::to_string(m_setD1));
417  log<text_log>("Quad 2 set points: " + std::to_string(m_setx2) + " " + std::to_string(m_sety2) + " " + std::to_string(m_setD2));
418  log<text_log>("Quad 3 set points: " + std::to_string(m_setx3) + " " + std::to_string(m_sety3) + " " + std::to_string(m_setD3));
419  log<text_log>("Quad 4 set points: " + std::to_string(m_setx4) + " " + std::to_string(m_sety4) + " " + std::to_string(m_setD4));
420  }
421  }
422  else
423  {
424  log<text_log>("Reference image " + reffits + " size does not match shmim stream.", logPrio::LOG_ERROR);
425  }
426  }
427  else
428  {
429  if(m_numPupils == 4 && !m_refUpdated)
430  {
431  m_setx1 = 29.5;
432  m_sety1 = 29.5;
433  m_setD1 = 56.0;
434 
435  m_setx2 = 89.5;
436  m_sety2 = 29.5;
437  m_setD2 = 56.0;
438 
439  m_setx3 = 29.5;
440  m_sety3 = 89.5;
441  m_setD3 = 56.0;
442 
443  m_setx4 = 89.5;
444  m_sety4 = 89.5;
445  m_setD4 = 56.0;
446  }
447  else if(!m_refUpdated)
448  {
449  m_setx1 = 30.0;
450  m_sety1 = 38.0;
451  m_setD1 = 14.0;
452 
453  m_setx2 = 96.0;
454  m_sety2 = 38.0;
455  m_setD2 = 14.0;
456 
457  m_setx3 = 65.0;
458  m_sety3 = 95.0;
459  m_setD3 = 14.0;
460  }
461  }
462 
463  uint32_t imsize[3];
464  imsize[0] = m_width;
465  imsize[1] = m_height;
466  imsize[2] = 1;
467 
468  if(m_threshShmimConnected)
469  {
470  ImageStreamIO_destroyIm( &m_threshShmim );
471  m_threshShmimConnected = false;
472  }
473 
474  if(m_edgeShmimConnected)
475  {
476  ImageStreamIO_destroyIm( &m_edgeShmim );
477  m_edgeShmimConnected = false;
478  }
479 
480  ImageStreamIO_createIm_gpu(&m_threshShmim , m_threshShmimName .c_str(), 3, imsize, m_dataType, -1, 1, IMAGE_NB_SEMAPHORE, 0, CIRCULAR_BUFFER | ZAXIS_TEMPORAL,0);
481  m_threshShmimConnected = true;
482 
483  ImageStreamIO_createIm_gpu(&m_edgeShmim , m_edgeShmimName .c_str(), 3, imsize, m_dataType, -1, 1, IMAGE_NB_SEMAPHORE, 0, CIRCULAR_BUFFER | ZAXIS_TEMPORAL,0);
484  m_edgeShmimConnected = true;
485 
486  if(m_edgeShmimConnected)
487  {
488  }
489 
490  return 0;
491 }
492 
493 inline
494 int pupilAlign::processImage( void* curr_src,
495  const dev::shmimT & dummy
496  )
497 {
498  static_cast<void>(dummy);
499 
500  for(unsigned nn=0; nn < m_width*m_height; ++nn)
501  {
502  m_fitIm.data()[nn] += ((float*)curr_src) [nn];
503  }
504 
505  ///\todo need a more robust corner averaging system here.
506  m_fitIm -= 0.25*( m_fitIm(0,0) + m_fitIm(0,m_height-1) + m_fitIm(m_width-1,m_height-1) + m_fitIm(m_width-1,0));
507 
508  m_fitter.m_thresh = m_threshold;
509 
510  m_fitter.fit(m_fitIm, m_edgeIm);
511 
512  {//mutex scope
513 
514  std::lock_guard<std::mutex> guard(m_indiMutex);
515  m_indiP_quad1["set-x"].set(m_setx1);
516  m_indiP_quad1["x"].set(m_fitter.m_avgx[0]);
517  m_indiP_quad1["dx"].set(m_fitter.m_avgx[0]-m_setx1);
518  m_indiP_quad1["set-y"].set(m_sety1);
519  m_indiP_quad1["y"].set(m_fitter.m_avgy[0]);
520  m_indiP_quad1["dy"].set(m_fitter.m_avgy[0]-m_sety1);
521  m_indiP_quad1["set-D"].set(m_setD1);
522  m_indiP_quad1["D"].set(2*m_fitter.m_avgr[0]);
523  m_indiP_quad1["dD"].set(2*m_fitter.m_avgr[0]-m_setD1);
524  m_indiP_quad1["med"].set(m_fitter.m_med[0]);
525  m_indiP_quad1.setState (INDI_BUSY);
526  m_indiDriver->sendSetProperty (m_indiP_quad1);
527 
528  m_indiP_quad2["set-x"].set(m_setx2);
529  m_indiP_quad2["x"].set(m_fitter.m_avgx[1]);
530  m_indiP_quad2["dx"].set(m_fitter.m_avgx[1]-m_setx2);
531  m_indiP_quad2["set-y"].set(m_sety2);
532  m_indiP_quad2["y"].set(m_fitter.m_avgy[1]);
533  m_indiP_quad2["dy"].set(m_fitter.m_avgy[1]-m_sety2);
534  m_indiP_quad2["set-D"].set(m_setD2);
535  m_indiP_quad2["D"].set(2*m_fitter.m_avgr[1]);
536  m_indiP_quad2["dD"].set(2*m_fitter.m_avgr[1]-m_setD2);
537  m_indiP_quad2["med"].set(m_fitter.m_med[1]);
538  m_indiP_quad2.setState (INDI_BUSY);
539  m_indiDriver->sendSetProperty (m_indiP_quad2);
540 
541  m_indiP_quad3["set-x"].set(m_setx3);
542  m_indiP_quad3["x"].set(m_fitter.m_avgx[2]);
543  m_indiP_quad3["dx"].set(m_fitter.m_avgx[2]-m_setx3);
544  m_indiP_quad3["set-y"].set(m_sety3);
545  m_indiP_quad3["y"].set(m_fitter.m_avgy[2]);
546  m_indiP_quad3["dy"].set(m_fitter.m_avgy[2]-m_sety3);
547  m_indiP_quad3["set-D"].set(m_setD3);
548  m_indiP_quad3["D"].set(2*m_fitter.m_avgr[2]);
549  m_indiP_quad3["dD"].set(2*m_fitter.m_avgr[2]-m_setD3);
550  m_indiP_quad3["med"].set(m_fitter.m_med[2]);
551  m_indiP_quad3.setState (INDI_BUSY);
552  m_indiDriver->sendSetProperty (m_indiP_quad3);
553 
554  if(m_numPupils == 3)
555  {
556  m_indiP_avg["x"].set(.333*(m_fitter.m_avgx[0] + m_fitter.m_avgx[1] + m_fitter.m_avgx[2]));
557  m_indiP_avg["y"].set(.333*(m_fitter.m_avgy[0] + m_fitter.m_avgy[1] + m_fitter.m_avgy[2]));
558  m_indiP_avg["D"].set(.667*(m_fitter.m_avgr[0] + m_fitter.m_avgr[1] + m_fitter.m_avgr[2]));
559 
560  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));
561  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));
562  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));
563  }
564  else
565  {
566  m_indiP_quad4["set-x"].set(m_setx4);
567  m_indiP_quad4["x"].set(m_fitter.m_avgx[3]);
568  m_indiP_quad4["dx"].set(m_fitter.m_avgx[3]-m_setx4);
569  m_indiP_quad4["set-y"].set(m_sety4);
570  m_indiP_quad4["y"].set(m_fitter.m_avgy[3]);
571  m_indiP_quad4["dy"].set(m_fitter.m_avgy[3]-m_sety4);
572  m_indiP_quad4["set-D"].set(m_setD4);
573  m_indiP_quad4["D"].set(2*m_fitter.m_avgr[3]);
574  m_indiP_quad4["dD"].set(2*m_fitter.m_avgr[3]-m_setD4);
575  m_indiP_quad4["med"].set(m_fitter.m_med[3]);
576  m_indiP_quad4.setState (INDI_BUSY);
577  m_indiDriver->sendSetProperty (m_indiP_quad4);
578 
579  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]));
580  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]));
581  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]));
582 
583  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));
584  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));
585  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));
586  m_indiDriver->sendSetProperty (m_indiP_avg);
587 
588  }
589 
590  }
591 
592 
593  if(m_averaging)
594  {
595  ++m_navg;
596 
597  m_avgx1_accum += m_fitter.m_avgx[0];
598  m_avgx1sq_accum += m_fitter.m_avgx[0]*m_fitter.m_avgx[0];
599 
600  m_avgy1_accum += m_fitter.m_avgy[0];
601  m_avgy1sq_accum += m_fitter.m_avgy[0]*m_fitter.m_avgy[0];
602 
603  m_avgD1_accum += 2*m_fitter.m_avgr[0];
604  m_avgD1sq_accum += 4*m_fitter.m_avgr[0]*m_fitter.m_avgr[0];
605 
606  m_avgmed1_accum += m_fitter.m_med[0];
607  m_avgmed1sq_accum += m_fitter.m_med[0]*m_fitter.m_med[0];
608 
609  m_avgx1 = m_avgx1_accum / m_navg;
610  m_varx1 = m_avgx1sq_accum / m_navg - m_avgx1*m_avgx1;
611 
612  m_avgy1 = m_avgy1_accum / m_navg;
613  m_vary1 = m_avgy1sq_accum / m_navg - m_avgy1*m_avgy1;
614 
615  m_avgD1 = m_avgD1_accum / m_navg;
616  m_varD1 = m_avgD1sq_accum / m_navg - m_avgD1*m_avgD1;
617 
618  m_avgmed1 = m_avgmed1_accum / m_navg;
619  m_varmed1 = m_avgmed1sq_accum / m_navg - m_avgmed1*m_avgmed1;
620 
621  m_avgx2_accum += m_fitter.m_avgx[1];
622  m_avgx2sq_accum += m_fitter.m_avgx[1]*m_fitter.m_avgx[1];
623 
624  m_avgy2_accum += m_fitter.m_avgy[1];
625  m_avgy2sq_accum += m_fitter.m_avgy[1]*m_fitter.m_avgy[1];
626 
627  m_avgD2_accum += 2*m_fitter.m_avgr[1];
628  m_avgD2sq_accum += 4*m_fitter.m_avgr[1]*m_fitter.m_avgr[1];
629 
630  m_avgmed2_accum += m_fitter.m_med[1];
631  m_avgmed2sq_accum += m_fitter.m_med[1]*m_fitter.m_med[1];
632 
633  m_avgx2 = m_avgx2_accum / m_navg;
634  m_varx2 = m_avgx2sq_accum / m_navg - m_avgx2*m_avgx2;
635 
636  m_avgy2 = m_avgy2_accum / m_navg;
637  m_vary2 = m_avgy2sq_accum / m_navg - m_avgy2*m_avgy2;
638 
639  m_avgD2 = m_avgD2_accum / m_navg;
640  m_varD2 = m_avgD2sq_accum / m_navg - m_avgD2*m_avgD2;
641 
642  m_avgmed2 = m_avgmed2_accum / m_navg;
643  m_varmed2 = m_avgmed2sq_accum / m_navg - m_avgmed2*m_avgmed2;
644 
645 
646 
647  m_avgx3_accum += m_fitter.m_avgx[2];
648  m_avgx3sq_accum += m_fitter.m_avgx[2]*m_fitter.m_avgx[2];
649 
650  m_avgy3_accum += m_fitter.m_avgy[2];
651  m_avgy3sq_accum += m_fitter.m_avgy[2]*m_fitter.m_avgy[2];
652 
653  m_avgD3_accum += 2*m_fitter.m_avgr[2];
654  m_avgD3sq_accum += 4*m_fitter.m_avgr[2]*m_fitter.m_avgr[2];
655 
656  m_avgmed3_accum += m_fitter.m_med[2];
657  m_avgmed3sq_accum += m_fitter.m_med[2]*m_fitter.m_med[2];
658 
659  m_avgx3 = m_avgx3_accum / m_navg;
660  m_varx3 = m_avgx3sq_accum / m_navg - m_avgx3*m_avgx3;
661 
662  m_avgy3 = m_avgy3_accum / m_navg;
663  m_vary3 = m_avgy3sq_accum / m_navg - m_avgy3*m_avgy3;
664 
665  m_avgD3 = m_avgD3_accum / m_navg;
666  m_varD3 = m_avgD3sq_accum / m_navg - m_avgD3*m_avgD3;
667 
668  m_avgmed3 = m_avgmed3_accum / m_navg;
669  m_varmed3 = m_avgmed3sq_accum / m_navg - m_avgmed3*m_avgmed3;
670 
671  if(m_numPupils == 3)
672  {
673  double tmp = 0.333*(m_fitter.m_avgx[0]+m_fitter.m_avgx[1]+m_fitter.m_avgx[2]+m_fitter.m_avgx[3]);
674  m_avgxAll_accum += tmp;
675  m_avgxAllsq_accum += tmp*tmp;
676 
677  tmp = 0.333*(m_fitter.m_avgy[0]+m_fitter.m_avgy[1]+m_fitter.m_avgy[2]);
678  m_avgyAll_accum += tmp;
679  m_avgyAllsq_accum += tmp*tmp;
680 
681  tmp = 2*0.333*(m_fitter.m_avgr[0]+m_fitter.m_avgr[1]+m_fitter.m_avgr[2]);
682  m_avgDAll_accum += tmp;
683  m_avgDAllsq_accum += tmp*tmp;
684 
685  tmp = 0.333*(m_fitter.m_med[0]+m_fitter.m_med[1]+m_fitter.m_med[2]);
686  m_avgmedAll_accum += tmp;
687  m_avgmedAllsq_accum += tmp*tmp;
688 
689  m_avgxAll = m_avgxAll_accum / m_navg;
690  m_varxAll = m_avgxAllsq_accum / m_navg - m_avgxAll*m_avgxAll;
691 
692  m_avgyAll = m_avgyAll_accum / m_navg;
693  m_varyAll = m_avgyAllsq_accum / m_navg - m_avgyAll*m_avgyAll;
694 
695  m_avgDAll = m_avgDAll_accum / m_navg;
696  m_varDAll = m_avgDAllsq_accum / m_navg - m_avgDAll*m_avgDAll;
697 
698  m_avgmedAll = m_avgmedAll_accum / m_navg;
699  m_varmedAll = m_avgmedAllsq_accum / m_navg - m_avgmedAll*m_avgmedAll;
700 
701 
702  std::cerr << "****************************************************************\n";
703  std::cerr << "Averaged: " << m_navg << "\n";
704  std::cerr << "Average x1: " << m_avgx1 << " +/- " << sqrt(m_varx1) << "\n";
705  std::cerr << "Average y1: " << m_avgy1 << " +/- " << sqrt(m_vary1) << "\n";
706  std::cerr << "Average D1: " << m_avgD1 << " +/- " << sqrt(m_varD1) << "\n";
707  std::cerr << "Average med1: " << m_avgmed1 << " +/- " << sqrt(m_varmed1) << "\n\n";
708  std::cerr << "Average x2: " << m_avgx2 << " +/- " << sqrt(m_varx2) << "\n";
709  std::cerr << "Average y2: " << m_avgy2 << " +/- " << sqrt(m_vary2) << "\n";
710  std::cerr << "Average D2: " << m_avgD2 << " +/- " << sqrt(m_varD2) << "\n";
711  std::cerr << "Average med2: " << m_avgmed2 << " +/- " << sqrt(m_varmed2) << "\n\n";
712  std::cerr << "Average x3: " << m_avgx3 << " +/- " << sqrt(m_varx3) << "\n";
713  std::cerr << "Average y3: " << m_avgy3 << " +/- " << sqrt(m_vary3) << "\n";
714  std::cerr << "Average D3: " << m_avgD3 << " +/- " << sqrt(m_varD3) << "\n";
715  std::cerr << "Average med3: " << m_avgmed3 << " +/- " << sqrt(m_varmed3) << "\n\n";
716  std::cerr << "Average xAll: " << m_avgxAll << " +/- " << sqrt(m_varxAll) << "\n";
717  std::cerr << "Average yAll: " << m_avgyAll << " +/- " << sqrt(m_varyAll) << "\n";
718  std::cerr << "Average DAll: " << m_avgDAll << " +/- " << sqrt(m_varDAll) << "\n";
719  std::cerr << "Average medAll: " << m_avgmedAll << " +/- " << sqrt(m_varmedAll) << "\n\n";
720  }
721  else
722  {
723  m_avgx4_accum += m_fitter.m_avgx[3];
724  m_avgx4sq_accum += m_fitter.m_avgx[3]*m_fitter.m_avgx[3];
725 
726  m_avgy4_accum += m_fitter.m_avgy[3];
727  m_avgy4sq_accum += m_fitter.m_avgy[3]*m_fitter.m_avgy[3];
728 
729  m_avgD4_accum += 2*m_fitter.m_avgr[3];
730  m_avgD4sq_accum += 4*m_fitter.m_avgr[3]*m_fitter.m_avgr[3];
731 
732  m_avgmed4_accum += m_fitter.m_med[3];
733  m_avgmed4sq_accum += m_fitter.m_med[3]*m_fitter.m_med[3];
734 
735  m_avgx4 = m_avgx4_accum / m_navg;
736  m_varx4 = m_avgx4sq_accum / m_navg - m_avgx4*m_avgx4;
737 
738  m_avgy4 = m_avgy4_accum / m_navg;
739  m_vary4 = m_avgy4sq_accum / m_navg - m_avgy4*m_avgy4;
740 
741  m_avgD4 = m_avgD4_accum / m_navg;
742  m_varD4 = m_avgD4sq_accum / m_navg - m_avgD4*m_avgD4;
743 
744  m_avgmed4 = m_avgmed4_accum / m_navg;
745  m_varmed4 = m_avgmed4sq_accum / m_navg - m_avgmed4*m_avgmed4;
746 
747 
748  double tmp = 0.25*(m_fitter.m_avgx[0]+m_fitter.m_avgx[1]+m_fitter.m_avgx[2]+m_fitter.m_avgx[3]);
749  m_avgxAll_accum += tmp;
750  m_avgxAllsq_accum += tmp*tmp;
751 
752  tmp = 0.25*(m_fitter.m_avgy[0]+m_fitter.m_avgy[1]+m_fitter.m_avgy[2]+m_fitter.m_avgy[3]);
753  m_avgyAll_accum += tmp;
754  m_avgyAllsq_accum += tmp*tmp;
755 
756  tmp = 2*0.25*(m_fitter.m_avgr[0]+m_fitter.m_avgr[1]+m_fitter.m_avgr[2]+m_fitter.m_avgr[3]);
757  m_avgDAll_accum += tmp;
758  m_avgDAllsq_accum += tmp*tmp;
759 
760  tmp = 0.25*(m_fitter.m_med[0]+m_fitter.m_med[1]+m_fitter.m_med[2]+m_fitter.m_med[3]);
761  m_avgmedAll_accum += tmp;
762  m_avgmedAllsq_accum += tmp*tmp;
763 
764  m_avgxAll = m_avgxAll_accum / m_navg;
765  m_varxAll = m_avgxAllsq_accum / m_navg - m_avgxAll*m_avgxAll;
766 
767  m_avgyAll = m_avgyAll_accum / m_navg;
768  m_varyAll = m_avgyAllsq_accum / m_navg - m_avgyAll*m_avgyAll;
769 
770  m_avgDAll = m_avgDAll_accum / m_navg;
771  m_varDAll = m_avgDAllsq_accum / m_navg - m_avgDAll*m_avgDAll;
772 
773  m_avgmedAll = m_avgmedAll_accum / m_navg;
774  m_varmedAll = m_avgmedAllsq_accum / m_navg - m_avgmedAll*m_avgmedAll;
775 
776 
777  std::cerr << "****************************************************************\n";
778  std::cerr << "Averaged: " << m_navg << "\n";
779  std::cerr << "Average x1: " << m_avgx1 << " +/- " << sqrt(m_varx1) << "\n";
780  std::cerr << "Average y1: " << m_avgy1 << " +/- " << sqrt(m_vary1) << "\n";
781  std::cerr << "Average D1: " << m_avgD1 << " +/- " << sqrt(m_varD1) << "\n";
782  std::cerr << "Average med1: " << m_avgmed1 << " +/- " << sqrt(m_varmed1) << "\n\n";
783  std::cerr << "Average x2: " << m_avgx2 << " +/- " << sqrt(m_varx2) << "\n";
784  std::cerr << "Average y2: " << m_avgy2 << " +/- " << sqrt(m_vary2) << "\n";
785  std::cerr << "Average D2: " << m_avgD2 << " +/- " << sqrt(m_varD2) << "\n";
786  std::cerr << "Average med2: " << m_avgmed2 << " +/- " << sqrt(m_varmed2) << "\n\n";
787  std::cerr << "Average x3: " << m_avgx3 << " +/- " << sqrt(m_varx3) << "\n";
788  std::cerr << "Average y3: " << m_avgy3 << " +/- " << sqrt(m_vary3) << "\n";
789  std::cerr << "Average D3: " << m_avgD3 << " +/- " << sqrt(m_varD3) << "\n";
790  std::cerr << "Average med3: " << m_avgmed3 << " +/- " << sqrt(m_varmed3) << "\n\n";
791  std::cerr << "Average x4: " << m_avgx4 << " +/- " << sqrt(m_varx4) << "\n";
792  std::cerr << "Average y4: " << m_avgy4 << " +/- " << sqrt(m_vary4) << "\n";
793  std::cerr << "Average D4: " << m_avgD4 << " +/- " << sqrt(m_varD4) << "\n";
794  std::cerr << "Average med4: " << m_avgmed4 << " +/- " << sqrt(m_varmed4) << "\n\n";
795  std::cerr << "Average xAll: " << m_avgxAll << " +/- " << sqrt(m_varxAll) << "\n";
796  std::cerr << "Average yAll: " << m_avgyAll << " +/- " << sqrt(m_varyAll) << "\n";
797  std::cerr << "Average DAll: " << m_avgDAll << " +/- " << sqrt(m_varDAll) << "\n";
798  std::cerr << "Average medAll: " << m_avgmedAll << " +/- " << sqrt(m_varmedAll) << "\n\n";
799  }
800  }
801 
802  m_threshShmim.md->write=1;
803  m_edgeShmim.md->write=1;
804 
805  clock_gettime(CLOCK_REALTIME, &m_threshShmim.md->writetime);
806  m_edgeShmim.md->writetime = m_threshShmim.md->writetime;
807 
808  m_threshShmim.md->atime = m_threshShmim.md->writetime;
809  m_edgeShmim.md->atime = m_threshShmim.md->writetime;
810 
811  m_threshShmim.md->cnt0++;
812  m_edgeShmim.md->cnt0++;
813 
814  memcpy(m_threshShmim.array.raw, m_fitIm.data(), m_fitIm.rows()*m_fitIm.cols()*sizeof(float));
815  memcpy(m_edgeShmim.array.raw, m_edgeIm.data(), m_edgeIm.rows()*m_edgeIm.cols()*sizeof(float));
816 
817  m_threshShmim.md->write=0;
818  m_edgeShmim.md->write=0;
819 
820  ImageStreamIO_sempost(&m_threshShmim,-1);
821  ImageStreamIO_sempost(&m_edgeShmim,-1);
822 
823  return 0;
824 }
825 
826 
827 INDI_NEWCALLBACK_DEFN(pupilAlign, m_indiP_thresh)(const pcf::IndiProperty & ipRecv)
828 {
829  if(ipRecv.getName() != m_indiP_thresh.getName())
830  {
831  log<software_error>({__FILE__,__LINE__, "wrong INDI property received."});
832  return -1;
833  }
834 
835  float target;
836 
837  if( indiTargetUpdate( m_indiP_thresh, target, ipRecv, true) < 0)
838  {
839  log<software_error>({__FILE__,__LINE__});
840  return -1;
841  }
842 
843  m_threshold = target;
844 
845  m_restart = true; //need to re-process the reference
846 
847  log<text_log>("set threshold = " + std::to_string(m_threshold), logPrio::LOG_NOTICE);
848  return 0;
849 }
850 
851 INDI_NEWCALLBACK_DEFN(pupilAlign, m_indiP_averaging)(const pcf::IndiProperty & ipRecv)
852 {
853  if(ipRecv.getName() != m_indiP_averaging.getName())
854  {
855  log<software_error>({__FILE__,__LINE__, "wrong INDI property received."});
856  return -1;
857  }
858 
859 
860 
861  if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On)
862  {
863  m_navg = 0;
864  m_averaging = true;
865 
866  m_avgx1_accum = 0;
867  m_avgx1sq_accum = 0;
868  m_avgy1_accum = 0;
869  m_avgy1sq_accum = 0;
870  m_avgD1_accum = 0;
871  m_avgD1sq_accum = 0;
872  m_avgmed1_accum = 0;
873  m_avgmed1sq_accum = 0;
874 
875  m_avgx2_accum = 0;
876  m_avgx2sq_accum = 0;
877  m_avgy2_accum = 0;
878  m_avgy2sq_accum = 0;
879  m_avgD2_accum = 0;
880  m_avgD2sq_accum = 0;
881  m_avgmed2_accum = 0;
882  m_avgmed2sq_accum = 0;
883 
884  m_avgx3_accum = 0;
885  m_avgx3sq_accum = 0;
886  m_avgy3_accum = 0;
887  m_avgy3sq_accum = 0;
888  m_avgD3_accum = 0;
889  m_avgD3sq_accum = 0;
890  m_avgmed3_accum = 0;
891  m_avgmed3sq_accum = 0;
892 
893  m_avgx4_accum = 0;
894  m_avgx4sq_accum = 0;
895  m_avgy4_accum = 0;
896  m_avgy4sq_accum = 0;
897  m_avgD4_accum = 0;
898  m_avgD4sq_accum = 0;
899  m_avgmed4_accum = 0;
900  m_avgmed4sq_accum = 0;
901 
902  m_avgxAll_accum = 0;
903  m_avgxAllsq_accum = 0;
904  m_avgyAll_accum = 0;
905  m_avgyAllsq_accum = 0;
906  m_avgDAll_accum = 0;
907  m_avgDAllsq_accum = 0;
908  m_avgmedAll_accum = 0;
909  m_avgmedAllsq_accum = 0;
910 
911  updateSwitchIfChanged(m_indiP_averaging, "toggle", pcf::IndiElement::On, INDI_BUSY);
912 
913  log<text_log>("began averaging");
914 
915  }
916  else if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::Off)
917  {
918  m_averaging = false;
919  updateSwitchIfChanged(m_indiP_averaging, "toggle", pcf::IndiElement::Off, INDI_IDLE);
920 
921  log<text_log>("stopped averaging");
922  }
923 
924  return 0;
925 }
926 
927 INDI_NEWCALLBACK_DEFN(pupilAlign, m_indiP_reload)(const pcf::IndiProperty & ipRecv)
928 {
929  if(ipRecv.getName() != m_indiP_reload.getName())
930  {
931  log<software_error>({__FILE__,__LINE__, "wrong INDI property received."});
932  return -1;
933  }
934 
935 
936 
937  if( ipRecv["request"].getSwitchState() == pcf::IndiElement::On)
938  {
939  log<text_log>("reloading");
940  m_restart = 1;
941  }
942 
943  return 0;
944 }
945 
946 INDI_NEWCALLBACK_DEFN(pupilAlign, m_indiP_update)(const pcf::IndiProperty & ipRecv)
947 {
948  if(ipRecv.getName() != m_indiP_update.getName())
949  {
950  log<software_error>({__FILE__,__LINE__, "wrong INDI property received."});
951  return -1;
952  }
953 
954 
955 
956  if( ipRecv["request"].getSwitchState() == pcf::IndiElement::On)
957  {
958  std::lock_guard<std::mutex> guard(m_indiMutex);
959 
960  log<text_log>("updating cal");
961  m_setx1 = m_indiP_quad1["x"].get<float>();
962  m_sety1 = m_indiP_quad1["y"].get<float>();
963  m_setD1 = m_indiP_quad1["D"].get<float>();
964 
965  m_setx2 = m_indiP_quad2["x"].get<float>();
966  m_sety2 = m_indiP_quad2["y"].get<float>();
967  m_setD2 = m_indiP_quad2["D"].get<float>();
968 
969  m_setx3 = m_indiP_quad3["x"].get<float>();
970  m_sety3 = m_indiP_quad3["y"].get<float>();
971  m_setD3 = m_indiP_quad3["D"].get<float>();
972 
973  if(m_numPupils == 4)
974  {
975  m_setx4 = m_indiP_quad4["x"].get<float>();
976  m_sety4 = m_indiP_quad4["y"].get<float>();
977  m_setD4 = m_indiP_quad4["D"].get<float>();
978  }
979 
980  m_refUpdated = true;
981  }
982 
983  return 0;
984 }
985 
986 } //namespace app
987 } //namespace MagAOX
988 
989 #endif //pupilAlign_hpp
int16_t pixelT
Definition: baslerCtrl.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 indiTargetUpdate(pcf::IndiProperty &localProperty, T &localTarget, const pcf::IndiProperty &remoteProperty, bool setBusy=true)
Get the target element value from an new property.
Definition: MagAOXApp.hpp:3197
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
The MagAO-X Pyramid Pupil Fitter.
Definition: pupilAlign.hpp:37
pcf::IndiProperty m_indiP_takeTgt
Definition: pupilAlign.hpp:152
std::string m_darkShmimName
The name of the dark shared memory stream. Default is <m_pupilShmimName>_dark.
Definition: pupilAlign.hpp:60
~pupilAlign() noexcept
D'tor, declared and defined for noexcept.
Definition: pupilAlign.hpp:165
virtual void loadConfig()
Definition: pupilAlign.hpp:216
pcf::IndiProperty m_indiP_takePupil
Definition: pupilAlign.hpp:149
virtual int appLogic()
Implementation of the FSM for pupilAlign.
Definition: pupilAlign.hpp:345
int allocate(const dev::shmimT &)
Definition: pupilAlign.hpp:370
int m_navg
Number of images to average. Default is 10.
Definition: pupilAlign.hpp:62
int processImage(void *curr_src, const dev::shmimT &)
Definition: pupilAlign.hpp:494
virtual void setupConfig()
Definition: pupilAlign.hpp:179
mx::improc::eigenImage< float > m_pupIm
Definition: pupilAlign.hpp:69
mx::improc::eigenImage< float > m_darkIm
Definition: pupilAlign.hpp:68
std::vector< pixelT > srcPos
Definition: pupilAlign.hpp:84
pupilAlign()
Default c'tor.
Definition: pupilAlign.hpp:159
virtual int appShutdown()
Shutdown the app.
Definition: pupilAlign.hpp:362
mx::improc::sourceFinder< float >::pixelT pixelT
Definition: pupilAlign.hpp:50
mx::improc::eigenImage< float > m_tgtIm
Definition: pupilAlign.hpp:70
dev::shmimMonitor< pupilAlign > shmimMonitorT
Definition: pupilAlign.hpp:45
mx::improc::sourceFinder< float > m_srcFind
Definition: pupilAlign.hpp:82
friend class pupilAlign_test
Definition: pupilAlign.hpp:40
virtual int appStartup()
Startup function.
Definition: pupilAlign.hpp:222
float m_threshold
The default SNR threshold for finding the pupil.
Definition: pupilAlign.hpp:64
mx::improc::eigenImage< float > m_tgtPupSubIm
Definition: pupilAlign.hpp:71
float realT
Floating point type in which to do all calculations.
Definition: pupilAlign.hpp:48
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
Definition: pupilAlign.hpp:198
pcf::IndiProperty m_indiP_navg
Definition: pupilAlign.hpp:139
pcf::IndiProperty m_indiP_tgtCoords
Definition: pupilAlign.hpp:146
std::string m_pupilShmimName
The name of the pupil shared memory image.
Definition: pupilAlign.hpp:58
INDI_NEWCALLBACK_DECL(pupilAlign, m_indiP_navg)
pcf::IndiProperty m_indiP_threshold
Definition: pupilAlign.hpp:143
#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()
const pcf::IndiProperty & ipRecv
Definition: MagAOXApp.hpp:3434
INDI_NEWCALLBACK_DEFN(acesxeCtrl, m_indiP_windspeed)(const pcf
Definition: acesxeCtrl.hpp:687
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
Software ERR log entry.