Line data Source code
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 0 : static std::string configSection()
26 : {
27 0 : return "refShmim";
28 : };
29 :
30 0 : static std::string indiPrefix()
31 : {
32 0 : return "refShmim";
33 : };
34 : };
35 :
36 :
37 : struct maskShmimT
38 : {
39 0 : static std::string configSection()
40 : {
41 0 : return "maskShmim";
42 : };
43 :
44 0 : static std::string indiPrefix()
45 : {
46 0 : 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
81 : typedef dev::shmimMonitor<refRMS,refShmimT> refShmimMonitorT;
82 : typedef dev::shmimMonitor<refRMS,maskShmimT> maskShmimMonitorT;
83 :
84 : ///Floating point type in which to do all calculations.
85 : typedef float realT;
86 :
87 : typedef int32_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};
102 : realT m_maskSum {0};
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 0 : ~refRMS() noexcept
121 0 : {}
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;
171 0 : INDI_SETCALLBACK_DECL(refRMS, m_indiP_fpsSource);
172 :
173 :
174 : };
175 :
176 : inline
177 : refRMS::refRMS() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
178 : {
179 :
180 : refShmimMonitorT::m_getExistingFirst = true;
181 : maskShmimMonitorT::m_getExistingFirst = true;
182 :
183 : return;
184 : }
185 :
186 : inline
187 0 : void refRMS::setupConfig()
188 : {
189 0 : refShmimMonitorT::setupConfig(config);
190 0 : maskShmimMonitorT::setupConfig(config);
191 :
192 0 : config.add("rms.fpsSource", "", "rms.fpsSource", argType::Required, "rms", "fpsSource", false, "string", "Device name for getting fps. This device should have *.fps.current.");
193 0 : }
194 :
195 : inline
196 0 : int refRMS::loadConfigImpl( mx::app::appConfigurator & _config )
197 : {
198 0 : refShmimMonitorT::loadConfig(config);
199 :
200 0 : maskShmimMonitorT::loadConfig(config);
201 :
202 0 : _config(m_fpsSource, "rms.fpsSource");
203 :
204 0 : return 0;
205 : }
206 :
207 : inline
208 0 : void refRMS::loadConfig()
209 : {
210 0 : loadConfigImpl(config);
211 0 : }
212 :
213 : inline
214 0 : int refRMS::appStartup()
215 : {
216 0 : createROIndiNumber( m_indiP_refrms, "refrms", "Reference RMS", "");
217 0 : indi::addNumberElement(m_indiP_refrms, "one_sec", 0, 1, 1000, "One Second rms");
218 0 : indi::addNumberElement(m_indiP_refrms, "two_sec", 0, 1, 1000, "Two Second rms");
219 0 : indi::addNumberElement(m_indiP_refrms, "five_sec", 0, 1, 1000, "Five Second rms");
220 0 : indi::addNumberElement(m_indiP_refrms, "ten_sec", 0, 1, 1000, "Five Second rms");
221 0 : registerIndiPropertyReadOnly(m_indiP_refrms);
222 :
223 0 : if(m_fpsSource != "")
224 : {
225 0 : REG_INDI_SETPROP(m_indiP_fpsSource, m_fpsSource, std::string("fps"));
226 : }
227 :
228 0 : if(refShmimMonitorT::appStartup() < 0)
229 : {
230 0 : return log<software_error,-1>({__FILE__, __LINE__});
231 : }
232 :
233 0 : if(maskShmimMonitorT::appStartup() < 0)
234 : {
235 0 : return log<software_error,-1>({__FILE__, __LINE__});
236 : }
237 :
238 0 : state(stateCodes::OPERATING);
239 :
240 0 : return 0;
241 : }
242 :
243 : inline
244 0 : int refRMS::appLogic()
245 : {
246 :
247 0 : if( refShmimMonitorT::appLogic() < 0)
248 : {
249 0 : return log<software_error,-1>({__FILE__,__LINE__});
250 : }
251 :
252 0 : if( maskShmimMonitorT::appLogic() < 0)
253 : {
254 0 : return log<software_error,-1>({__FILE__,__LINE__});
255 : }
256 :
257 0 : if( m_rms.size() > 0 )
258 : {
259 0 : if(m_rms.size() >= m_rms.maxEntries())
260 : {
261 0 : m_rms_1sec = 0;
262 0 : if(m_rms.size() > 1.0*m_fps)
263 : {
264 0 : int N = 0;
265 0 : for(size_t n=0; n < 1.0*m_fps; ++n)
266 : {
267 0 : m_rms_1sec += m_rms[n];
268 0 : ++N;
269 : }
270 0 : m_rms_1sec /= N;
271 :
272 0 : std::cerr << m_rms_1sec << " ";
273 :
274 : }
275 :
276 0 : m_rms_2sec = 0;
277 0 : if(m_rms.size() > 2.0*m_fps)
278 : {
279 0 : int N = 0;
280 0 : for(size_t n=0; n < 2.0*m_fps; ++n)
281 : {
282 0 : m_rms_2sec += m_rms[n];
283 0 : ++N;
284 : }
285 0 : m_rms_2sec /= N;
286 :
287 0 : std::cerr << m_rms_2sec << " ";
288 : }
289 :
290 0 : m_rms_5sec = 0;
291 0 : if(m_rms.size() > 5.0*m_fps)
292 : {
293 0 : int N = 0;
294 0 : for(size_t n=0; n < 5.0*m_fps; ++n)
295 : {
296 0 : m_rms_5sec += m_rms[n];
297 0 : ++N;
298 : }
299 0 : m_rms_5sec /= N;
300 :
301 0 : std::cerr << m_rms_5sec << " ";
302 : }
303 :
304 0 : m_rms_10sec = 0;
305 0 : if(m_rms.size() > 10.0*m_fps)
306 : {
307 0 : int N = 0;
308 0 : for(size_t n=0; n < 10.0*m_fps; ++n)
309 : {
310 0 : m_rms_10sec += m_rms[n];
311 0 : ++N;
312 : }
313 0 : m_rms_10sec /= N;
314 :
315 0 : std::cerr << m_rms_10sec << " ";
316 : }
317 :
318 0 : std::cerr << "\n";
319 :
320 0 : 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 0 : std::unique_lock<std::mutex> lock(m_indiMutex);
327 :
328 0 : if(refShmimMonitorT::updateINDI() < 0)
329 : {
330 0 : log<software_error>({__FILE__, __LINE__});
331 : }
332 :
333 0 : if(maskShmimMonitorT::updateINDI() < 0)
334 : {
335 0 : log<software_error>({__FILE__, __LINE__});
336 : }
337 :
338 0 : return 0;
339 0 : }
340 :
341 : inline
342 0 : int refRMS::appShutdown()
343 : {
344 0 : refShmimMonitorT::appShutdown();
345 0 : maskShmimMonitorT::appShutdown();
346 :
347 0 : return 0;
348 : }
349 :
350 :
351 : inline
352 0 : int refRMS::allocate(const refShmimT & dummy)
353 : {
354 : static_cast<void>(dummy); //be unused
355 :
356 0 : std::unique_lock<std::mutex> lock(m_indiMutex);
357 :
358 0 : m_currRef.resize(refShmimMonitorT::m_width, refShmimMonitorT::m_height);
359 :
360 0 : std::cerr << "got ref: " << refShmimMonitorT::m_width << " " << refShmimMonitorT::m_height << "\n";
361 :
362 0 : if(m_mask.rows() != m_currRef.rows() || m_mask.cols() != m_currRef.cols())
363 : {
364 0 : m_maskValid = false;
365 0 : m_mask.resize(m_currRef.rows(), m_currRef.cols());
366 0 : m_mask.setConstant(1);
367 : }
368 :
369 0 : while(m_fps == 0)
370 : {
371 0 : sleep(5);
372 : /*if(m_fps == 0)
373 : {
374 : return log<text_log,-1>("fps not updated", logPrio::LOG_ERROR);
375 : }*/
376 : }
377 :
378 0 : cbIndexT cbSz = 11 * m_fps;
379 0 : m_mean.maxEntries(cbSz);
380 0 : m_rms.maxEntries(cbSz);
381 :
382 0 : std::cerr << "allocated\n";
383 :
384 0 : return 0;
385 0 : }
386 :
387 : inline
388 0 : 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 0 : 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 0 : if(m_mask.rows() != m_currRef.rows() || m_mask.cols() != m_currRef.cols())
401 : {
402 0 : std::cerr << m_mask.rows() << " " << m_mask.cols() << "\n";
403 0 : std::cerr << m_currRef.rows() << " " << m_currRef.cols() << "\n";
404 :
405 0 : return 0;
406 : }
407 :
408 : //mult by mask, etc.
409 0 : float mean = (m_currRef * m_mask).sum()/m_maskSum;
410 0 : float rms = sqrt(((m_currRef - mean)*m_mask).square().sum()/m_maskSum);
411 :
412 0 : m_mean.nextEntry(mean);
413 0 : m_rms.nextEntry(rms);
414 :
415 0 : return 0;
416 : }
417 :
418 :
419 : inline
420 0 : int refRMS::allocate(const maskShmimT & dummy)
421 : {
422 : static_cast<void>(dummy); //be unused
423 :
424 0 : std::unique_lock<std::mutex> lock(m_indiMutex);
425 :
426 0 : std::cerr << "got mask: " << maskShmimMonitorT::m_width << " " << maskShmimMonitorT::m_height << "\n";
427 :
428 0 : m_mask.resize(maskShmimMonitorT::m_width, maskShmimMonitorT::m_height);
429 :
430 0 : return 0;
431 0 : }
432 :
433 : inline
434 0 : 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 0 : m_mask = Eigen::Map<Eigen::Matrix<float,-1,-1>>((float *)curr_src, maskShmimMonitorT::m_width,maskShmimMonitorT::m_height);
442 :
443 0 : m_maskSum = m_mask.sum();
444 :
445 0 : if(m_mask.rows() == m_currRef.rows() || m_mask.cols() == m_currRef.cols())
446 : {
447 0 : m_maskValid = true;
448 : }
449 :
450 0 : return 0;
451 : }
452 :
453 0 : INDI_SETCALLBACK_DEFN( refRMS, m_indiP_fpsSource )(const pcf::IndiProperty &ipRecv)
454 : {
455 0 : if( ipRecv.getName() != m_indiP_fpsSource.getName())
456 : {
457 0 : log<software_error>({__FILE__, __LINE__, "Invalid INDI property."});
458 0 : return -1;
459 : }
460 :
461 0 : if( ipRecv.find("current") != true ) //this isn't valie
462 : {
463 0 : return 0;
464 : }
465 :
466 : //std::lock<std::mutex> mut(m_indiMutex);
467 :
468 0 : realT fps = ipRecv["current"].get<float>();
469 : //mut.unlock();
470 :
471 0 : if(fps != m_fps)
472 : {
473 0 : m_fps = fps;
474 0 : std::cout << "Got fps: " << m_fps << "\n";
475 0 : refShmimMonitorT::m_restart = true;
476 : }
477 :
478 0 : return 0;
479 : }
480 :
481 : } //namespace app
482 : } //namespace MagAOX
483 :
484 : #endif //refRMS_hpp
|