API
 
Loading...
Searching...
No Matches
strehlEstimator.hpp
Go to the documentation of this file.
1/** \file strehlEstimator.hpp
2 * \brief The MagAO-X XXXXXX header file
3 *
4 * \ingroup strehlEstimator_files
5 */
6
7#ifndef strehlEstimator_hpp
8#define strehlEstimator_hpp
9
10#include <mx/ao/analysis/aoSystem.hpp>
11using namespace mx::math;
12
13#include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
14#include "../../magaox_git_version.h"
15
16/** \defgroup strehlEstimator
17 * \brief The XXXXXX application to do YYYYYYY
18 *
19 * <a href="../handbook/operating/software/apps/XXXXXX.html">Application Documentation</a>
20 *
21 * \ingroup apps
22 *
23 */
24
25/** \defgroup strehlEstimator_files
26 * \ingroup strehlEstimator
27 */
28
29namespace MagAOX
30{
31namespace app
32{
33
34struct wfsavgShmimT
35{
36 static std::string configSection()
37 {
38 return "wfsavgShmim";
39 };
40
41 static std::string indiPrefix()
42 {
43 return "wfsavg";
44 };
45};
46
47struct wfsmaskShmimT
48{
49 static std::string configSection()
50 {
51 return "wfsmaskShmim";
52 };
53
54 static std::string indiPrefix()
55 {
56 return "wfsmask";
57 };
58};
59
60/// The MagAO-X xxxxxxxx
61/**
62 * \ingroup strehlEstimator
63 */
64class strehlEstimator : public MagAOXApp<true>,
65 dev::shmimMonitor<strehlEstimator, wfsavgShmimT>,
66 dev::shmimMonitor<strehlEstimator, wfsmaskShmimT>
67{
68
69 // Give the test harness access.
71
74
75 public:
78
79 protected:
80 /** \name Configurable Parameters
81 *@{
82 */
83
84 int m_loopNum{ 1 }; ///< The number of the loop. Used to set shmim names, as in aolN_wfsmask.
85
86 std::string m_wfsDevice{ "camwfs" };
87
88 std::string m_stagebsDevice{ "stagebs" };
89
90 float m_again{ 28.547 };
91
92 float m_qe{ 0.53 };
93
94 float m_F0_6535{ 4.2e10 };
95
96 float m_F0_HaIR{ 5.3e10 };
97
98 float m_lam0_6535{ 0.791 };
99
100 float m_lam0_HaIR{ 0.837 };
101
102 float m_qe_6535{ 0.53 };
103
104 float m_qe_HaIR{ 0.53 };
105
106 ///@}
107
108 float m_fps{ 2000 };
109
110 float m_emg{ 1 };
111
112 float m_F0{ m_F0_6535 };
113
115
116 float m_seeing{ 0.64 };
117
118 float m_r0{ 0.16 };
119
120 float m_elevation{ 90 };
121
123
124 float m_counts{ 0 };
125
126 float m_mag{ 0 };
127
128 mx::improc::eigenImage<float> m_wfsmask;
129 mx::improc::eigenImage<float> m_wfsavg;
130
131 mx::AO::analysis::aoSystem<float, mx::AO::analysis::vonKarmanSpectrum<float>> m_aosys;
132
133 double m_dimm_fwhm_corr{ 0 }; ///< DIMM elevation corrected FWHM
134 int m_dimm_time{ 0 }; ///< Seconds since midnight of DIMM measurement.
135
136 double m_mag1_fwhm_corr{ 0 }; ///< MAG1 elevation corrected FWHM
137 int m_mag1_time{ 0 }; ///< Seconds since midnight of MAG1 measurement.
138
139 double m_mag2_fwhm_corr{ 0 }; ///< MAG2 elevation corrected FWHM
140 int m_mag2_time{ 0 }; ///< Seconds since midnight of MAG2 measurement.
141
142 public:
143 /// Default c'tor.
145
146 /// D'tor, declared and defined for noexcept.
150
151 virtual void setupConfig();
152
153 /// Implementation of loadConfig logic, separated for testing.
154 /** This is called by loadConfig().
155 */
156 int loadConfigImpl(
157 mx::app::appConfigurator &_config /**< [in] an application configuration from which to load values*/ );
158
159 virtual void loadConfig();
160
161 /// Startup function
162 /**
163 *
164 */
165 virtual int appStartup();
166
167 /// Implementation of the FSM for strehlEstimator.
168 /**
169 * \returns 0 on no critical error
170 * \returns -1 on an error requiring shutdown
171 */
172 virtual int appLogic();
173
174 /// Shutdown the app.
175 /**
176 *
177 */
178 virtual int appShutdown();
179
180 int allocate( const wfsavgShmimT & ///< [in] tag to differentiate shmimMonitor parents.
181 );
182
183 int processImage( void *curr_src, ///< [in] pointer to the start of the current frame
184 const wfsavgShmimT & ///< [in] tag to differentiate shmimMonitor parents.
185 );
186
187 int allocate( const wfsmaskShmimT & ///< [in] tag to differentiate shmimMonitor parents.
188 );
189
190 int processImage( void *curr_src, ///< [in] pointer to the start of the current frame
191 const wfsmaskShmimT & ///< [in] tag to differentiate shmimMonitor parents.
192 );
193
194 void calcMag();
195
196 /** INDI
197 * @{
198 */
199
200 pcf::IndiProperty m_indiP_fps;
201 pcf::IndiProperty m_indiP_emg;
202
203 pcf::IndiProperty m_indiP_stage;
204
205 pcf::IndiProperty m_indiP_tcsi_seeing;
206 pcf::IndiProperty m_indiP_tcsi_telpos;
207 pcf::IndiProperty m_indiP_seeing_magaox;
208
209 pcf::IndiProperty m_indiP_mag;
210 pcf::IndiProperty m_indiP_strehl;
211 pcf::IndiProperty m_indiP_wfe;
212
218
219 ///@}
220};
221
222strehlEstimator::strehlEstimator() : MagAOXApp( MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED )
223{
224
227
228 return;
229}
230
232{
233 m_aosys.loadMagAOX();
234
235 config.add( "loop.number",
236 "",
237 "loop.number",
238 argType::Required,
239 "loop",
240 "number",
241 false,
242 "int",
243 "The number of the loop. Used to set shmim names, as in aolN_mgainfact." );
244
245 config.add( "phot.qe_6535",
246 "",
247 "phot.qe_6535",
248 argType::Required,
249 "phot",
250 "qe_6535",
251 false,
252 "float",
253 "The WFS QE in the 65-35 B/S." );
254
255 config.add( "phot.qe_HaIR",
256 "",
257 "phot.qe_HaIR",
258 argType::Required,
259 "phot",
260 "qe_HaIR",
261 false,
262 "float",
263 "The WFS QE in the Ha-IR B/S." );
264
267}
268
269int strehlEstimator::loadConfigImpl( mx::app::appConfigurator &_config )
270{
271
272 _config( m_loopNum, "loop.number" );
273
274 _config( m_qe_6535, "phot.qe_6535" );
275 _config( m_qe_HaIR, "phot.qe_HaIR" );
276
277 char shmim[1024];
278 snprintf( shmim, sizeof( shmim ), "aol%d_wfsavg", m_loopNum );
281
282 snprintf( shmim, sizeof( shmim ), "aol%d_wfsmask", m_loopNum );
285
286 return 0;
287}
288
290{
291 loadConfigImpl( config );
292}
293
295{
296
299
301
303
305
306 REG_INDI_SETPROP( m_indiP_tcsi_seeing, "tcsi", "seeing" );
307 REG_INDI_SETPROP( m_indiP_tcsi_telpos, "tcsi", "telpos" );
308
309 CREATE_REG_INDI_RO_NUMBER( m_indiP_mag, "star_mag", "Star Magnitude", "Error Budget" );
310 m_indiP_mag.add( pcf::IndiElement( "current", 0 ) );
311
312 CREATE_REG_INDI_RO_NUMBER( m_indiP_strehl, "strehl_optimal", "Strehl", "Error Budget" );
313 m_indiP_strehl.add( pcf::IndiElement( "pyramid", 0 ) );
314
315 CREATE_REG_INDI_RO_NUMBER( m_indiP_wfe, "wfe_predicted", "WFE", "Error Budget" );
316 m_indiP_wfe.add( pcf::IndiElement( "total", 0 ) );
317 m_indiP_wfe.add( pcf::IndiElement( "measurement", 0 ) );
318 m_indiP_wfe.add( pcf::IndiElement( "time_delay", 0 ) );
319 m_indiP_wfe.add( pcf::IndiElement( "fitting", 0 ) );
320
322
323 return 0;
324}
325
327{
330
333
334 m_aosys.starMag( m_mag );
335 m_aosys.F0( m_qe * m_F0 );
336 m_aosys.lam_wfs( m_lam0 * 1e-6 );
337 m_aosys.lam_sci( m_lam0 * 1e-6 );
338 m_aosys.ron_wfs( std::vector<float>( { 245.0f / m_emg } ) );
339 m_aosys.npix_wfs( std::vector<float>( { 1.0f * m_npix } ) );
340 m_aosys.minTauWFS( std::vector<float>( { 1.0f / m_fps } ) );
341 m_aosys.tauWFS( 1. / m_fps );
342 m_aosys.atm.r_0( m_r0, 0.5e-6 );
343 m_aosys.zeta( ( 90. - m_elevation ) * 3.14159 / 180. );
344
345 updateIfChanged( m_indiP_strehl, "pyramid", m_aosys.strehl() );
347 { "total", "measurement", "time_delay", "fitting" },
348 { sqrt( m_aosys.wfeVar() ) * ( 1000 * m_lam0 / two_pi<float>() ),
349 sqrt( m_aosys.measurementErrorTotal() ) * ( 1000 * m_lam0 / two_pi<float>() ),
350 sqrt( m_aosys.timeDelayErrorTotal() ) * ( 1000 * m_lam0 / two_pi<float>() ),
351 sqrt( m_aosys.fittingErrorTotal() ) * ( 1000 * m_lam0 / two_pi<float>() ) } );
352 return 0;
353}
354
362
364{
365 static_cast<void>( dummy );
366
367 std::cerr << "Got WFS avg: " << wfsavgShmimMonitorT::m_width << " x " << wfsavgShmimMonitorT::m_height << '\n';
368 return 0;
369}
370
371int strehlEstimator::processImage( void *curr_src, const wfsavgShmimT &dummy )
372{
373 static_cast<void>( dummy );
374
375 m_wfsavg = mx::improc::eigenMap<float>(
377
378 if( m_wfsavg.rows() == m_wfsmask.rows() && m_wfsavg.cols() == m_wfsmask.cols() )
379 {
380 m_counts = ( m_wfsavg * m_wfsmask ).sum();
381
382 std::cerr << "counts: " << m_counts << '\n';
383
384 calcMag();
385 }
386
387 return 0;
388}
389
391{
392 static_cast<void>( dummy );
393
394 std::cerr << "Got WFS mask: " << wfsmaskShmimMonitorT::m_width << " x " << wfsmaskShmimMonitorT::m_height << '\n';
395 return 0;
396}
397
398int strehlEstimator::processImage( void *curr_src, const wfsmaskShmimT &dummy )
399{
400 static_cast<void>( dummy );
401
402 m_wfsmask = mx::improc::eigenMap<float>(
404
405 m_npix = m_wfsmask.sum();
406
407 if( m_wfsavg.rows() == m_wfsmask.rows() && m_wfsavg.cols() == m_wfsmask.cols() )
408 {
409 // update counts because we might have been waiting on this.
410 m_counts = ( m_wfsavg * m_wfsmask ).sum();
411
412 calcMag();
413 }
414
415 return 0;
416}
417
419{
420 std::cerr << "calcMag: " << m_counts << ' ' << m_again << ' ' << ' ' << m_emg << ' ' << m_fps << ' ' << m_qe << ' '
421 << m_F0 << '\n';
422
423 m_mag = -2.5 * log10( m_counts * m_again / m_emg * m_fps / ( m_qe * m_F0 ) );
424
425 updateIfChanged( m_indiP_mag, "current", m_mag );
426}
427
428INDI_SETCALLBACK_DEFN( strehlEstimator, m_indiP_fps )( const pcf::IndiProperty &ipRecv )
429{
430 INDI_VALIDATE_CALLBACK_PROPS( m_indiP_fps, ipRecv );
431
432 if( ipRecv.find( "current" ) )
433 {
434 float fps = ipRecv["current"].get<float>();
435
436 if( fps != m_fps )
437 {
438 m_fps = fps;
439 std::cerr << "Got FPS: " << m_fps << '\n';
440
441 calcMag();
442 }
443 }
444 return 0;
445}
446
447INDI_SETCALLBACK_DEFN( strehlEstimator, m_indiP_emg )( const pcf::IndiProperty &ipRecv )
448{
449 INDI_VALIDATE_CALLBACK_PROPS( m_indiP_emg, ipRecv );
450
451 if( ipRecv.find( "current" ) )
452 {
453 float emg = ipRecv["current"].get<float>();
454
455 if( emg != m_emg )
456 {
457 m_emg = emg;
458 std::cerr << "Got EMG: " << m_emg << '\n';
459
460 calcMag();
461 }
462 }
463 return 0;
464}
465
466INDI_SETCALLBACK_DEFN( strehlEstimator, m_indiP_stage )( const pcf::IndiProperty &ipRecv )
467{
468 INDI_VALIDATE_CALLBACK_PROPS( m_indiP_stage, ipRecv );
469
470 // if( ipRecv.find( "presetName" ) )
471 {
472 std::string preset = "none";
473
474 for( auto &&el : ipRecv.getElements() )
475 {
476 if( el.second.getSwitchState() == pcf::IndiElement::On )
477 {
478 preset = el.first;
479 break;
480 }
481 }
482
483 std::cerr << "Got stage bs: " << preset << '\n';
484
485 if( preset == "ha-ir" )
486 {
487 m_F0 = m_F0_HaIR;
488 m_lam0 = m_lam0_HaIR;
489 m_qe = m_qe_HaIR;
490 }
491 else
492 {
493 m_F0 = m_F0_6535;
494 m_lam0 = m_lam0_6535;
495 m_qe = m_qe_6535;
496 }
497
498 calcMag();
499 }
500
501 return 0;
502}
503
504INDI_SETCALLBACK_DEFN( strehlEstimator, m_indiP_tcsi_seeing )( const pcf::IndiProperty &ipRecv )
505{
506 INDI_VALIDATE_CALLBACK_PROPS( m_indiP_tcsi_seeing, ipRecv );
507
508 if( ipRecv.find( "dimm_fwhm" ) )
509 {
510 float seeing = ipRecv["dimm_fwhm"].get<float>();
511
512 if( seeing != m_seeing )
513 {
514 m_seeing = seeing;
515 std::cerr << "Got seeing: " << m_seeing << '\n';
516
517 m_r0 = 0.2063 * 0.5 / m_seeing;
518 }
519 }
520 return 0;
521}
522
523INDI_SETCALLBACK_DEFN( strehlEstimator, m_indiP_tcsi_telpos )( const pcf::IndiProperty &ipRecv )
524{
525 INDI_VALIDATE_CALLBACK_PROPS( m_indiP_tcsi_telpos, ipRecv );
526
527 if( ipRecv.find( "el" ) )
528 {
529 float elevation = ipRecv["el"].get<float>();
530
531 if( elevation != m_elevation )
532 {
533 m_elevation = elevation;
534 std::cerr << "Got elevation: " << m_elevation << '\n';
535 }
536 }
537 return 0;
538}
539
540} // namespace app
541} // namespace MagAOX
542
543#endif // strehlEstimator_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.
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.
uint32_t m_width
The width of the images in the stream.
uint32_t m_height
The height of the images in the stream.
virtual int appShutdown()
Shutdown the app.
INDI_SETCALLBACK_DECL(strehlEstimator, m_indiP_tcsi_telpos)
INDI_SETCALLBACK_DECL(strehlEstimator, m_indiP_tcsi_seeing)
double m_dimm_fwhm_corr
DIMM elevation corrected FWHM.
virtual int appStartup()
Startup function.
mx::AO::analysis::aoSystem< float, mx::AO::analysis::vonKarmanSpectrum< float > > m_aosys
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
~strehlEstimator() noexcept
D'tor, declared and defined for noexcept.
INDI_SETCALLBACK_DECL(strehlEstimator, m_indiP_stage)
virtual int appLogic()
Implementation of the FSM for strehlEstimator.
double m_mag1_fwhm_corr
MAG1 elevation corrected FWHM.
pcf::IndiProperty m_indiP_tcsi_seeing
int m_mag1_time
Seconds since midnight of MAG1 measurement.
int allocate(const wfsavgShmimT &)
dev::shmimMonitor< strehlEstimator, wfsmaskShmimT > wfsmaskShmimMonitorT
int m_loopNum
The number of the loop. Used to set shmim names, as in aolN_wfsmask.
int processImage(void *curr_src, const wfsavgShmimT &)
int m_dimm_time
Seconds since midnight of DIMM measurement.
INDI_SETCALLBACK_DECL(strehlEstimator, m_indiP_emg)
dev::shmimMonitor< strehlEstimator, wfsavgShmimT > wfsavgShmimMonitorT
mx::improc::eigenImage< float > m_wfsavg
mx::improc::eigenImage< float > m_wfsmask
double m_mag2_fwhm_corr
MAG2 elevation corrected FWHM.
INDI_SETCALLBACK_DECL(strehlEstimator, m_indiP_fps)
int m_mag2_time
Seconds since midnight of MAG2 measurement.
pcf::IndiProperty m_indiP_seeing_magaox
pcf::IndiProperty m_indiP_tcsi_telpos
#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
Definition dm.hpp:26
#define SHMIMMONITORT_APP_STARTUP(SHMIMMONITORT)
Call shmimMonitorT::appStartup with error checking for a typedef-ed shmimMonitor.
#define SHMIMMONITORT_UPDATE_INDI(SHMIMMONITORT)
Call shmimMonitorT::updateINDI with error checking for a typedef-ed 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 SHMIMMONITORT_LOAD_CONFIG(SHMIMMONITORT, cfig)
Call shmimMonitorT::loadConfig with error checking for a typedef-ed shmimMonitor.
static std::string configSection()
static std::string indiPrefix()
static std::string indiPrefix()
static std::string configSection()