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