API
 
Loading...
Searching...
No Matches
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
27namespace MagAOX
28{
29namespace app
30{
31
32/// The MagAO-X Pyramid Pupil Fitter
33/**
34 * \ingroup pupilAlign
35 */
36class 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
50 typedef typename mx::improc::sourceFinder<float>::pixelT pixelT;
51
52protected:
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
74 bool m_pupShmimConnected {false};
75
77 bool m_tgtShmimConnected {false};
78
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
91public:
92 /// Default c'tor.
93 pupilAlign();
94
95 /// D'tor, declared and defined for 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
133
134
135 /** \name INDI
136 * @{
137 */
138
140
142
145
147
148
151
154
155 ///@}
156};
157
158inline
163
164inline
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
178inline
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
197inline
198int pupilAlign::loadConfigImpl( mx::app::appConfigurator & _config )
199{
200 m_shmimName = "camwfs_avg";
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
215inline
217{
218 loadConfigImpl(config);
219}
220
221inline
223{
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 {
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 {
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 {
337 return -1;
338 }
340
341 return 0;
342}
343
344inline
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
361inline
363{
365
366 return 0;
367}
368
369inline
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
493inline
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
827INDI_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 {
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
851INDI_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
927INDI_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
946INDI_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
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.
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.
stateCodes::stateCodeT state()
Get the current state code.
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.
indiDriver< MagAOXApp > * m_indiDriver
The INDI driver wrapper. Constructed and initialized by execute, which starts and stops communication...
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.
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
int createROIndiNumber(pcf::IndiProperty &prop, const std::string &propName, const std::string &propLabel="", const std::string &propGroup="")
Create a ReadOnly INDI Number property.
int registerIndiPropertyReadOnly(pcf::IndiProperty &prop)
Register an INDI property which is read only.
std::mutex m_indiMutex
Mutex for locking INDI communications.
int indiTargetUpdate(pcf::IndiProperty &localProperty, T &localTarget, const pcf::IndiProperty &remoteProperty, bool setBusy=true)
Get the target element value from an new property.
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.
pcf::IndiProperty m_indiP_takeTgt
std::string m_darkShmimName
The name of the dark shared memory stream. Default is <m_pupilShmimName>_dark.
~pupilAlign() noexcept
D'tor, declared and defined for noexcept.
virtual void loadConfig()
pcf::IndiProperty m_indiP_takePupil
virtual int appLogic()
Implementation of the FSM for pupilAlign.
int allocate(const dev::shmimT &)
int m_navg
Number of images to average. Default is 10.
int processImage(void *curr_src, const dev::shmimT &)
virtual void setupConfig()
mx::improc::eigenImage< float > m_pupIm
mx::improc::eigenImage< float > m_darkIm
std::vector< pixelT > srcPos
pupilAlign()
Default c'tor.
virtual int appShutdown()
Shutdown the app.
mx::improc::sourceFinder< float >::pixelT pixelT
mx::improc::eigenImage< float > m_tgtIm
dev::shmimMonitor< pupilAlign > shmimMonitorT
mx::improc::sourceFinder< float > m_srcFind
friend class pupilAlign_test
virtual int appStartup()
Startup function.
float m_threshold
The default SNR threshold for finding the pupil.
mx::improc::eigenImage< float > m_tgtPupSubIm
float realT
Floating point type in which to do all calculations.
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
pcf::IndiProperty m_indiP_navg
pcf::IndiProperty m_indiP_tgtCoords
std::string m_pupilShmimName
The name of the pupil shared memory image.
pcf::IndiProperty m_indiP_threshold
#define INDI_NEWCALLBACK_DEFN(class, prop)
Define the callback for a new property request.
#define INDI_NEWCALLBACK(prop)
Get the name of the static callback wrapper for a new property.
#define INDI_NEWCALLBACK_DECL(class, prop)
Declare the callback for a new property request, and declare and define the static wrapper.
@ OPERATING
The device is operating, other than homing.
#define INDI_IDLE
Definition indiUtils.hpp:28
#define INDI_BUSY
Definition indiUtils.hpp:30
const pcf::IndiProperty & ipRecv
Definition dm.hpp:24
static constexpr logPrioT LOG_NOTICE
A normal but significant condition.
static constexpr logPrioT LOG_ERROR
An error has occured which the software will attempt to correct.
Software ERR log entry.