API
refRMS.hpp
Go to the documentation of this file.
1 /** \file refRMS.hpp
2  * \brief The MagAO-X user gain control app
3  *
4  * \ingroup app_files
5  */
6 
7 #ifndef refRMS_hpp
8 #define refRMS_hpp
9 
10 #include <limits>
11 
12 #include <mx/improc/eigenCube.hpp>
13 #include <mx/improc/eigenImage.hpp>
14 
15 #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
16 #include "../../magaox_git_version.h"
17 
18 namespace MagAOX
19 {
20 namespace app
21 {
22 
23 struct refShmimT
24 {
25  static std::string configSection()
26  {
27  return "refShmim";
28  };
29 
30  static std::string indiPrefix()
31  {
32  return "refShmim";
33  };
34 };
35 
36 
37 struct maskShmimT
38 {
39  static std::string configSection()
40  {
41  return "maskShmim";
42  };
43 
44  static std::string indiPrefix()
45  {
46  return "maskShmim";
47  };
48 };
49 
50 /** \defgroup refRMS Calculate the RMS of the ref subtracted image
51  * \brief Calculates the r.m.s. of the reference subtracted WFS image.
52  *
53  * <a href="../handbook/operating/software/apps/refRMS.html">Application Documentation</a>
54  *
55  * \ingroup apps
56  *
57  */
58 
59 /** \defgroup refRMS_files User Gain Control
60  * \ingroup refRMS
61  */
62 
63 /** MagAO-X application to calculate the RMS of the reference subtracted WFS image.
64  *
65  * \ingroup refRMS
66  *
67  */
68 class refRMS : public MagAOXApp<true>, public dev::shmimMonitor<refRMS, refShmimT>,
69  public dev::shmimMonitor<refRMS,maskShmimT>
70 {
71 
72  //Give the test harness access.
73  friend class refRMS_test;
74 
75  friend class dev::shmimMonitor<refRMS,refShmimT>;
76  friend class dev::shmimMonitor<refRMS,maskShmimT>;
77 
78 public:
79 
80  //The base shmimMonitor type
83 
84  ///Floating point type in which to do all calculations.
85  typedef float realT;
86 
87  typedef uint16_t cbIndexT;
88 
89 protected:
90 
91  /** \name Configurable Parameters
92  *@{
93  */
94 
95  std::string m_fpsSource; ///< Device name for getting fps. This device should have *.fps.current.
96 
97  ///@}
98 
99  mx::improc::eigenImage<realT> m_currRef;
100  mx::improc::eigenImage<realT> m_mask;
101  bool m_maskValid {false};
103 
104  mx::sigproc::circularBufferIndex<float, cbIndexT> m_rms;
105 
106  mx::sigproc::circularBufferIndex<float, cbIndexT> m_mean;
107 
108  double m_rms_1sec;
109  double m_rms_2sec;
110  double m_rms_5sec;
111  double m_rms_10sec;
112 
113  float m_fps {0}; ///< Current FPS from the FPS source.
114 
115 public:
116  /// Default c'tor.
117  refRMS();
118 
119  /// D'tor, declared and defined for noexcept.
120  ~refRMS() noexcept
121  {}
122 
123  virtual void setupConfig();
124 
125  /// Implementation of loadConfig logic, separated for testing.
126  /** This is called by loadConfig().
127  */
128  int loadConfigImpl( mx::app::appConfigurator & _config /**< [in] an application configuration from which to load values*/);
129 
130  virtual void loadConfig();
131 
132  /// Startup function
133  /**
134  *
135  */
136  virtual int appStartup();
137 
138  /// Implementation of the FSM for refRMS.
139  /**
140  * \returns 0 on no critical error
141  * \returns -1 on an error requiring shutdown
142  */
143  virtual int appLogic();
144 
145  /// Shutdown the app.
146  /**
147  *
148  */
149  virtual int appShutdown();
150 
151 protected:
152 
153 
154  int allocate( const refShmimT & dummy /**< [in] tag to differentiate shmimMonitor parents.*/);
155 
156  int processImage( void * curr_src, ///< [in] pointer to start of current frame.
157  const refShmimT & dummy ///< [in] tag to differentiate shmimMonitor parents.
158  );
159 
160 
161  int allocate( const maskShmimT & dummy /**< [in] tag to differentiate shmimMonitor parents.*/);
162 
163  int processImage( void * curr_src, ///< [in] pointer to start of current frame.
164  const maskShmimT & dummy ///< [in] tag to differentiate shmimMonitor parents.
165  );
166 
167 
168  pcf::IndiProperty m_indiP_refrms;
169 
170  pcf::IndiProperty m_indiP_fpsSource;
172 
173 
174 };
175 
176 inline
177 refRMS::refRMS() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
178 {
179 
182 
183  return;
184 }
185 
186 inline
188 {
191 
192  config.add("rms.fpsSource", "", "rms.fpsSource", argType::Required, "rms", "fpsSource", false, "string", "Device name for getting fps. This device should have *.fps.current.");
193 }
194 
195 inline
196 int refRMS::loadConfigImpl( mx::app::appConfigurator & _config )
197 {
199 
201 
202  _config(m_fpsSource, "rms.fpsSource");
203 
204  return 0;
205 }
206 
207 inline
209 {
210  loadConfigImpl(config);
211 }
212 
213 inline
215 {
216  createROIndiNumber( m_indiP_refrms, "refrms", "Reference RMS", "");
217  indi::addNumberElement(m_indiP_refrms, "one_sec", 0, 1, 1000, "One Second rms");
218  indi::addNumberElement(m_indiP_refrms, "two_sec", 0, 1, 1000, "Two Second rms");
219  indi::addNumberElement(m_indiP_refrms, "five_sec", 0, 1, 1000, "Five Second rms");
220  indi::addNumberElement(m_indiP_refrms, "ten_sec", 0, 1, 1000, "Five Second rms");
222 
223  if(m_fpsSource != "")
224  {
225  REG_INDI_SETPROP(m_indiP_fpsSource, m_fpsSource, std::string("fps"));
226  }
227 
229  {
230  return log<software_error,-1>({__FILE__, __LINE__});
231  }
232 
234  {
235  return log<software_error,-1>({__FILE__, __LINE__});
236  }
237 
239 
240  return 0;
241 }
242 
243 inline
245 {
246 
247  if( refShmimMonitorT::appLogic() < 0)
248  {
249  return log<software_error,-1>({__FILE__,__LINE__});
250  }
251 
252  if( maskShmimMonitorT::appLogic() < 0)
253  {
254  return log<software_error,-1>({__FILE__,__LINE__});
255  }
256 
257  if( m_rms.size() > 0 )
258  {
259  if(m_rms.size() >= m_rms.maxEntries())
260  {
261  m_rms_1sec = 0;
262  if(m_rms.size() > 1.0*m_fps)
263  {
264  int N = 0;
265  for(size_t n=0; n < 1.0*m_fps; ++n)
266  {
267  m_rms_1sec += m_rms[n];
268  ++N;
269  }
270  m_rms_1sec /= N;
271 
272  std::cerr << m_rms_1sec << " ";
273 
274  }
275 
276  m_rms_2sec = 0;
277  if(m_rms.size() > 2.0*m_fps)
278  {
279  int N = 0;
280  for(size_t n=0; n < 2.0*m_fps; ++n)
281  {
282  m_rms_2sec += m_rms[n];
283  ++N;
284  }
285  m_rms_2sec /= N;
286 
287  std::cerr << m_rms_2sec << " ";
288  }
289 
290  m_rms_5sec = 0;
291  if(m_rms.size() > 5.0*m_fps)
292  {
293  int N = 0;
294  for(size_t n=0; n < 5.0*m_fps; ++n)
295  {
296  m_rms_5sec += m_rms[n];
297  ++N;
298  }
299  m_rms_5sec /= N;
300 
301  std::cerr << m_rms_5sec << " ";
302  }
303 
304  m_rms_10sec = 0;
305  if(m_rms.size() > 10.0*m_fps)
306  {
307  int N = 0;
308  for(size_t n=0; n < 10.0*m_fps; ++n)
309  {
310  m_rms_10sec += m_rms[n];
311  ++N;
312  }
313  m_rms_10sec /= N;
314 
315  std::cerr << m_rms_10sec << " ";
316  }
317 
318  std::cerr << "\n";
319 
320  updateIfChanged(m_indiP_refrms, std::vector<std::string>({"one_sec","two_sec","five_sec","ten_sec"}), std::vector<double>({m_rms_1sec, m_rms_2sec, m_rms_5sec, m_rms_10sec}));
321 
322  }
323  }
324 
325 
326  std::unique_lock<std::mutex> lock(m_indiMutex);
327 
329  {
330  log<software_error>({__FILE__, __LINE__});
331  }
332 
334  {
335  log<software_error>({__FILE__, __LINE__});
336  }
337 
338  return 0;
339 }
340 
341 inline
343 {
346 
347  return 0;
348 }
349 
350 
351 inline
352 int refRMS::allocate(const refShmimT & dummy)
353 {
354  static_cast<void>(dummy); //be unused
355 
356  std::unique_lock<std::mutex> lock(m_indiMutex);
357 
359 
360  std::cerr << "got ref: " << refShmimMonitorT::m_width << " " << refShmimMonitorT::m_height << "\n";
361 
362  if(m_mask.rows() != m_currRef.rows() || m_mask.cols() != m_currRef.cols())
363  {
364  m_maskValid = false;
365  m_mask.resize(m_currRef.rows(), m_currRef.cols());
366  m_mask.setConstant(1);
367  }
368 
369  while(m_fps == 0)
370  {
371  sleep(5);
372  /*if(m_fps == 0)
373  {
374  return log<text_log,-1>("fps not updated", logPrio::LOG_ERROR);
375  }*/
376  }
377 
378  cbIndexT cbSz = 11 * m_fps;
379  m_mean.maxEntries(cbSz);
380  m_rms.maxEntries(cbSz);
381 
382  std::cerr << "allocated\n";
383 
384  return 0;
385 }
386 
387 inline
388 int refRMS::processImage( void * curr_src,
389  const refShmimT & dummy
390  )
391 {
392  static_cast<void>(dummy); //be unused
393 
394  //Copy it out first so we can afford to be slow and skipping frames
395  m_currRef = Eigen::Map<Eigen::Matrix<float,-1,-1>>((float *)curr_src, refShmimMonitorT::m_width, refShmimMonitorT::m_height);//,1);
396 
397  //std::cerr << "pi\n";
398 
399  //If mask has changed we skip
400  if(m_mask.rows() != m_currRef.rows() || m_mask.cols() != m_currRef.cols())
401  {
402  std::cerr << m_mask.rows() << " " << m_mask.cols() << "\n";
403  std::cerr << m_currRef.rows() << " " << m_currRef.cols() << "\n";
404 
405  return 0;
406  }
407 
408  //mult by mask, etc.
409  float mean = (m_currRef * m_mask).sum()/m_maskSum;
410  float rms = sqrt(((m_currRef - mean)*m_mask).square().sum()/m_maskSum);
411 
412  m_mean.nextEntry(mean);
413  m_rms.nextEntry(rms);
414 
415  return 0;
416 }
417 
418 
419 inline
420 int refRMS::allocate(const maskShmimT & dummy)
421 {
422  static_cast<void>(dummy); //be unused
423 
424  std::unique_lock<std::mutex> lock(m_indiMutex);
425 
426  std::cerr << "got mask: " << maskShmimMonitorT::m_width << " " << maskShmimMonitorT::m_height << "\n";
427 
429 
430  return 0;
431 }
432 
433 inline
434 int refRMS::processImage( void * curr_src,
435  const maskShmimT & dummy
436  )
437 {
438  static_cast<void>(dummy); //be unused
439 
440  //copy curr_src to mask
441  m_mask = Eigen::Map<Eigen::Matrix<float,-1,-1>>((float *)curr_src, maskShmimMonitorT::m_width,maskShmimMonitorT::m_height);
442 
443  m_maskSum = m_mask.sum();
444 
445  if(m_mask.rows() == m_currRef.rows() || m_mask.cols() == m_currRef.cols())
446  {
447  m_maskValid = true;
448  }
449 
450  return 0;
451 }
452 
453 INDI_SETCALLBACK_DEFN( refRMS, m_indiP_fpsSource )(const pcf::IndiProperty &ipRecv)
454 {
455  if( ipRecv.getName() != m_indiP_fpsSource.getName())
456  {
457  log<software_error>({__FILE__, __LINE__, "Invalid INDI property."});
458  return -1;
459  }
460 
461  if( ipRecv.find("current") != true ) //this isn't valie
462  {
463  return 0;
464  }
465 
466  //std::lock<std::mutex> mut(m_indiMutex);
467 
468  realT fps = ipRecv["current"].get<float>();
469  //mut.unlock();
470 
471  if(fps != m_fps)
472  {
473  m_fps = fps;
474  std::cout << "Got fps: " << m_fps << "\n";
475  refShmimMonitorT::m_restart = true;
476  }
477 
478  return 0;
479 }
480 
481 } //namespace app
482 } //namespace MagAOX
483 
484 #endif //refRMS_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.
Definition: MagAOXApp.hpp:3120
stateCodes::stateCodeT state()
Get the current state code.
Definition: MagAOXApp.hpp:2297
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
Definition: MagAOXApp.hpp:1804
int createROIndiNumber(pcf::IndiProperty &prop, const std::string &propName, const std::string &propLabel="", const std::string &propGroup="")
Create a ReadOnly INDI Number property.
Definition: MagAOXApp.hpp:2517
int registerIndiPropertyReadOnly(pcf::IndiProperty &prop)
Register an INDI property which is read only.
Definition: MagAOXApp.hpp:2655
std::mutex m_indiMutex
Mutex for locking INDI communications.
Definition: MagAOXApp.hpp:545
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.
int appShutdown()
Shuts down the shmimMonitor thread.
int loadConfig(mx::app::appConfigurator &config)
load the configuration system results
bool m_getExistingFirst
If set to true by derivedT, any existing image will be grabbed and sent to processImage before waitin...
int processImage(void *curr_src, const refShmimT &dummy)
Definition: refRMS.hpp:388
refRMS()
Default c'tor.
Definition: refRMS.hpp:177
mx::sigproc::circularBufferIndex< float, cbIndexT > m_rms
Definition: refRMS.hpp:104
dev::shmimMonitor< refRMS, maskShmimT > maskShmimMonitorT
Definition: refRMS.hpp:82
virtual int appShutdown()
Shutdown the app.
Definition: refRMS.hpp:342
friend class refRMS_test
Definition: refRMS.hpp:73
std::string m_fpsSource
Device name for getting fps. This device should have *.fps.current.
Definition: refRMS.hpp:95
~refRMS() noexcept
D'tor, declared and defined for noexcept.
Definition: refRMS.hpp:120
int allocate(const refShmimT &dummy)
Definition: refRMS.hpp:352
virtual int appStartup()
Startup function.
Definition: refRMS.hpp:214
virtual int appLogic()
Implementation of the FSM for refRMS.
Definition: refRMS.hpp:244
float realT
Floating point type in which to do all calculations.
Definition: refRMS.hpp:85
mx::sigproc::circularBufferIndex< float, cbIndexT > m_mean
Definition: refRMS.hpp:106
INDI_SETCALLBACK_DECL(refRMS, m_indiP_fpsSource)
mx::improc::eigenImage< realT > m_currRef
Definition: refRMS.hpp:99
virtual void setupConfig()
Definition: refRMS.hpp:187
uint16_t cbIndexT
Definition: refRMS.hpp:87
virtual void loadConfig()
Definition: refRMS.hpp:208
float m_fps
Current FPS from the FPS source.
Definition: refRMS.hpp:113
mx::improc::eigenImage< realT > m_mask
Definition: refRMS.hpp:100
pcf::IndiProperty m_indiP_refrms
Definition: refRMS.hpp:168
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
Definition: refRMS.hpp:196
dev::shmimMonitor< refRMS, refShmimT > refShmimMonitorT
Definition: refRMS.hpp:81
pcf::IndiProperty m_indiP_fpsSource
Definition: refRMS.hpp:170
#define REG_INDI_SETPROP(prop, devName, propName)
Register a SET INDI property with the class, using the standard callback name.
Definition: indiMacros.hpp:282
@ OPERATING
The device is operating, other than homing.
Definition: stateCodes.hpp:55
std::ostream & cerr()
std::ostream & cout()
int addNumberElement(pcf::IndiProperty &prop, const std::string &name, const T &min, const T &max, const T &step, const std::string &format, const std::string &label="")
Add a standard INDI Number element.
Definition: indiUtils.hpp:63
const pcf::IndiProperty & ipRecv
Definition: MagAOXApp.hpp:3434
INDI_SETCALLBACK_DEFN(adcTracker, m_indiP_teldata)(const pcf
Definition: adcTracker.hpp:461
std::unique_lock< std::mutex > lock(m_indiMutex)
Definition: dm.hpp:24
static std::string indiPrefix()
Definition: refRMS.hpp:44
static std::string configSection()
Definition: refRMS.hpp:39
static std::string indiPrefix()
Definition: refRMS.hpp:30
static std::string configSection()
Definition: refRMS.hpp:25
Software ERR log entry.