Line data Source code
1 : /** \file modalGainOpt.hpp
2 : * \brief The MagAO-X PSD-based gain optimizer header file
3 : *
4 : * \ingroup modalGainOpt_files
5 : */
6 :
7 : #ifndef modalGainOpt_hpp
8 : #define modalGainOpt_hpp
9 :
10 : #include <mx/mxException.hpp>
11 : #include <mx/ao/analysis/clGainOpt.hpp>
12 : #include <mx/ao/analysis/clAOLinearPredictor.hpp>
13 :
14 : #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
15 : #include "../../magaox_git_version.h"
16 :
17 : /** \defgroup modalGainOpt
18 : * \brief The MagAO-X application to perform PSD-based gain optimization
19 : *
20 : * <a href="../handbook/operating/software/apps/modalGainOpt.html">Application Documentation</a>
21 : *
22 : * \ingroup apps
23 : *
24 : */
25 :
26 : /** \defgroup modalGainOpt_files
27 : * \ingroup modalGainOpt
28 : */
29 :
30 : namespace MagAOX
31 : {
32 : namespace app
33 : {
34 :
35 : #define MGO_BREADCRUMB
36 :
37 : // #define MGO_BREADCRUMB std::cerr << __FILE__ << ' ' << __LINE__ << '\n';
38 :
39 : struct psdShmimT
40 : {
41 0 : static std::string configSection()
42 : {
43 0 : return "psdShmim";
44 : };
45 :
46 0 : static std::string indiPrefix()
47 : {
48 0 : return "psd";
49 : };
50 : };
51 :
52 : struct freqShmimT
53 : {
54 0 : static std::string configSection()
55 : {
56 0 : return "freqShmim";
57 : };
58 :
59 0 : static std::string indiPrefix()
60 : {
61 0 : return "freq";
62 : };
63 : };
64 :
65 : struct gainFactShmimT
66 : {
67 0 : static std::string configSection()
68 : {
69 0 : return "gainFactShmim";
70 : };
71 :
72 0 : static std::string indiPrefix()
73 : {
74 0 : return "gainFact";
75 : };
76 : };
77 :
78 : struct multFactShmimT
79 : {
80 0 : static std::string configSection()
81 : {
82 0 : return "multFactShmim";
83 : };
84 :
85 0 : static std::string indiPrefix()
86 : {
87 0 : return "multFact";
88 : };
89 : };
90 :
91 : struct pcGainFactShmimT
92 : {
93 0 : static std::string configSection()
94 : {
95 0 : return "pcGainFactShmim";
96 : };
97 :
98 0 : static std::string indiPrefix()
99 : {
100 0 : return "pcGainFact";
101 : };
102 : };
103 :
104 : struct pcMultFactShmimT
105 : {
106 0 : static std::string configSection()
107 : {
108 0 : return "pcMultFactShmim";
109 : };
110 :
111 0 : static std::string indiPrefix()
112 : {
113 0 : return "pcMultFact";
114 : };
115 : };
116 :
117 : struct numpccoeffShmimT
118 : {
119 0 : static std::string configSection()
120 : {
121 0 : return "numpccoeffShmim";
122 : };
123 :
124 0 : static std::string indiPrefix()
125 : {
126 0 : return "numpccoeff";
127 : };
128 : };
129 :
130 : struct acoeffShmimT
131 : {
132 0 : static std::string configSection()
133 : {
134 0 : return "acoeffShmim";
135 : };
136 :
137 0 : static std::string indiPrefix()
138 : {
139 0 : return "acoeff";
140 : };
141 : };
142 :
143 : struct bcoeffShmimT
144 : {
145 0 : static std::string configSection()
146 : {
147 0 : return "bcoeffShmim";
148 : };
149 :
150 0 : static std::string indiPrefix()
151 : {
152 0 : return "bcoeff";
153 : };
154 : };
155 :
156 : struct gainCalShmimT
157 : {
158 0 : static std::string configSection()
159 : {
160 0 : return "gainCalShmim";
161 : };
162 :
163 0 : static std::string indiPrefix()
164 : {
165 0 : return "gainCal";
166 : };
167 : };
168 :
169 : struct gainCalFactShmimT
170 : {
171 0 : static std::string configSection()
172 : {
173 0 : return "gainCalFactShmim";
174 : };
175 :
176 0 : static std::string indiPrefix()
177 : {
178 0 : return "gainCalFact";
179 : };
180 : };
181 :
182 : struct tauShmimT
183 : {
184 0 : static std::string configSection()
185 : {
186 0 : return "tauShmim";
187 : };
188 :
189 0 : static std::string indiPrefix()
190 : {
191 0 : return "tau";
192 : };
193 : };
194 :
195 : struct noiseShmimT
196 : {
197 0 : static std::string configSection()
198 : {
199 0 : return "noiseShmim";
200 : };
201 :
202 0 : static std::string indiPrefix()
203 : {
204 0 : return "noise";
205 : };
206 : };
207 :
208 : struct wfsavgShmimT
209 : {
210 0 : static std::string configSection()
211 : {
212 0 : return "wfsavgShmim";
213 : };
214 :
215 0 : static std::string indiPrefix()
216 : {
217 0 : return "wfsavg";
218 : };
219 : };
220 :
221 : struct wfsmaskShmimT
222 : {
223 0 : static std::string configSection()
224 : {
225 0 : return "wfsmaskShmim";
226 : };
227 :
228 0 : static std::string indiPrefix()
229 : {
230 0 : return "wfsmask";
231 : };
232 : };
233 :
234 : /// The MagAO-X PSD-based gain optimizer
235 : /**
236 : * \ingroup modalGainOpt
237 : */
238 : class modalGainOpt : public MagAOXApp<true>,
239 : dev::shmimMonitor<modalGainOpt, psdShmimT>,
240 : dev::shmimMonitor<modalGainOpt, freqShmimT>,
241 : dev::shmimMonitor<modalGainOpt, gainFactShmimT>,
242 : dev::shmimMonitor<modalGainOpt, multFactShmimT>,
243 : dev::shmimMonitor<modalGainOpt, pcGainFactShmimT>,
244 : dev::shmimMonitor<modalGainOpt, pcMultFactShmimT>,
245 : dev::shmimMonitor<modalGainOpt, numpccoeffShmimT>,
246 : dev::shmimMonitor<modalGainOpt, acoeffShmimT>,
247 : dev::shmimMonitor<modalGainOpt, bcoeffShmimT>,
248 : dev::shmimMonitor<modalGainOpt, gainCalShmimT>,
249 : dev::shmimMonitor<modalGainOpt, gainCalFactShmimT>,
250 : dev::shmimMonitor<modalGainOpt, tauShmimT>,
251 : dev::shmimMonitor<modalGainOpt, noiseShmimT>,
252 : dev::shmimMonitor<modalGainOpt, wfsavgShmimT>,
253 : dev::shmimMonitor<modalGainOpt, wfsmaskShmimT>
254 :
255 : {
256 :
257 : // Give the test harness access.
258 : friend class modalGainOpt_test;
259 :
260 : friend class dev::shmimMonitor<modalGainOpt, psdShmimT>;
261 : friend class dev::shmimMonitor<modalGainOpt, freqShmimT>;
262 : friend class dev::shmimMonitor<modalGainOpt, gainFactShmimT>;
263 : friend class dev::shmimMonitor<modalGainOpt, multFactShmimT>;
264 : friend class dev::shmimMonitor<modalGainOpt, pcGainFactShmimT>;
265 : friend class dev::shmimMonitor<modalGainOpt, pcMultFactShmimT>;
266 : friend class dev::shmimMonitor<modalGainOpt, numpccoeffShmimT>;
267 : friend class dev::shmimMonitor<modalGainOpt, acoeffShmimT>;
268 : friend class dev::shmimMonitor<modalGainOpt, bcoeffShmimT>;
269 : friend class dev::shmimMonitor<modalGainOpt, gainCalShmimT>;
270 : friend class dev::shmimMonitor<modalGainOpt, gainCalFactShmimT>;
271 : friend class dev::shmimMonitor<modalGainOpt, tauShmimT>;
272 : friend class dev::shmimMonitor<modalGainOpt, noiseShmimT>;
273 : friend class dev::shmimMonitor<modalGainOpt, wfsavgShmimT>;
274 : friend class dev::shmimMonitor<modalGainOpt, wfsmaskShmimT>;
275 :
276 : public:
277 : typedef dev::shmimMonitor<modalGainOpt, psdShmimT> psdShmimMonitorT;
278 : typedef dev::shmimMonitor<modalGainOpt, freqShmimT> freqShmimMonitorT;
279 : typedef dev::shmimMonitor<modalGainOpt, gainFactShmimT> gainFactShmimMonitorT;
280 : typedef dev::shmimMonitor<modalGainOpt, multFactShmimT> multFactShmimMonitorT;
281 : typedef dev::shmimMonitor<modalGainOpt, pcGainFactShmimT> pcGainFactShmimMonitorT;
282 : typedef dev::shmimMonitor<modalGainOpt, pcMultFactShmimT> pcMultFactShmimMonitorT;
283 : typedef dev::shmimMonitor<modalGainOpt, numpccoeffShmimT> numpccoeffShmimMonitorT;
284 : typedef dev::shmimMonitor<modalGainOpt, acoeffShmimT> acoeffShmimMonitorT;
285 : typedef dev::shmimMonitor<modalGainOpt, bcoeffShmimT> bcoeffShmimMonitorT;
286 : typedef dev::shmimMonitor<modalGainOpt, gainCalShmimT> gainCalShmimMonitorT;
287 : typedef dev::shmimMonitor<modalGainOpt, gainCalFactShmimT> gainCalFactShmimMonitorT;
288 : typedef dev::shmimMonitor<modalGainOpt, tauShmimT> tauShmimMonitorT;
289 : typedef dev::shmimMonitor<modalGainOpt, noiseShmimT> noiseShmimMonitorT;
290 : typedef dev::shmimMonitor<modalGainOpt, wfsavgShmimT> wfsavgShmimMonitorT;
291 : typedef dev::shmimMonitor<modalGainOpt, wfsmaskShmimT> wfsmaskShmimMonitorT;
292 :
293 : typedef std::chrono::time_point<std::chrono::steady_clock> timePointT;
294 : typedef std::chrono::duration<double> durationT;
295 :
296 : protected:
297 : /** \name Configurable Parameters
298 : *@{
299 : */
300 :
301 : int m_loopNum{ 1 }; ///< The number of the loop. Used to set shmim names, as in aolN_mgainfact.
302 :
303 : std::string m_loopName; ///< The name of the loop control INDI device name.
304 :
305 : std::string m_wfsDevice{ "camwfs" };
306 :
307 : std::string m_psdDevice{ "hopsds" }; /**< The INDI device name of the PSD calculator. Defaults to aolN_modevalPSDs
308 : where N is m_loopNum.*/
309 :
310 : std::string m_opticalGainDevice {"strehl"};
311 : std::string m_opticalGainProperty {"strehl_optimal"};
312 : std::string m_opticalGainElement {"pyramid"};
313 :
314 : bool m_autoUpdate{ false }; ///< Flag controlling whether gains are automatically updated
315 : bool m_opticalGainUpdate {false}; ///< Flag controlling whether optical gain is automatically updated;
316 :
317 : float m_gainGain{ 0.1 }; ///< The gain to use for closed-loop gain updates. Default is 0.1.
318 :
319 : uint32_t m_maxNCoeff{ 1000 };
320 :
321 : uint32_t m_defaultNCoeff{ 25 };
322 :
323 : int m_extrapOL {0}; ///< Which extrapolation method to use for the OL PSD. 0 is none. The only other option is 1.
324 :
325 : ///@}
326 :
327 : uint32_t m_nFreq{ 0 };
328 : uint32_t m_nModes{ 0 };
329 :
330 : bool m_updateOnce{ false }; ///< Flag to trigger a single update with gain.
331 :
332 : bool m_dump{ false }; ///< Flag to trigger a single update with no gain.
333 :
334 : float m_fps{ 0 };
335 :
336 : /// Each mode gets its own gain optimizer
337 : std::vector<mx::AO::analysis::clGainOpt<float>> m_goptCurrent;
338 : std::vector<mx::AO::analysis::clGainOpt<float>> m_goptSI;
339 : std::vector<mx::AO::analysis::clGainOpt<float>> m_goptLP;
340 : std::vector<mx::AO::analysis::clAOLinearPredictor<float>> m_linPred;
341 :
342 : bool m_goptUpdated{ true }; ///< Tracks if a parameter has updated requiring updates to the m_gopt entries.
343 : bool m_pcgoptUpdated{ true }; ///< Tracks if a parameter has updated requiring updates to the m_gopt entries.
344 :
345 : bool m_freqUpdated{ true }; /**< Tracks if the frequency scale has updated, which necessitates additional calcs.
346 : If true, implies m_goptUpdate == true.*/
347 : float m_psdTime{ 1 };
348 : float m_psdAvgTime{ 10 };
349 : float m_psdOverlapFraction{ 0.5 };
350 :
351 : std::vector<float> m_freq;
352 :
353 : mx::improc::eigenImage<float> m_clPSDs;
354 : mx::improc::eigenImage<float> m_clXferCurrent;
355 : mx::improc::eigenImage<float> m_clXferSI;
356 : mx::improc::eigenImage<float> m_clXferLP;
357 :
358 : std::vector<std::vector<float>> m_olPSDs;
359 : std::vector<std::vector<float>> m_nPSDs;
360 :
361 : std::vector<float> m_modeVarCL;
362 : std::vector<float> m_modeVarOL;
363 :
364 : int m_modesOn;
365 :
366 : std::vector<float> m_optGainSI;
367 : std::vector<float> m_gmaxSI; ///< The previously calculated maximum gains for LP
368 : std::vector<float> m_modeVarSI;
369 : std::vector<int> m_timesOnSI;
370 : int m_modesOnSI;
371 :
372 : std::vector<float> m_optGainLP;
373 : std::vector<float> m_gmaxLP; ///< The previously calculated maximum gains for LP
374 : std::vector<float> m_modeVarLP;
375 : std::vector<int> m_timesOnLP;
376 : int m_modesOnLP;
377 :
378 : bool m_loop{ false };
379 :
380 : float m_opticalGain{ 1 };
381 :
382 : float m_opticalGainSource {1};
383 :
384 : float m_gain{ 0 };
385 :
386 : float m_mult{ 1 };
387 :
388 : float m_siGain{ 0 };
389 :
390 : float m_siMult{ 1 };
391 :
392 : bool m_doPCCalcs{ true };
393 :
394 : float m_pcGain{ 0 };
395 :
396 : float m_pcMult{ 0 };
397 :
398 : bool m_pcOn{ false };
399 :
400 : std::vector<float> m_gainFacts;
401 :
402 : std::vector<float> m_multFacts;
403 :
404 : std::vector<float> m_pcGainFacts;
405 :
406 : std::vector<float> m_pcMultFacts;
407 :
408 : std::vector<uint32_t> m_Na; // The latest user specified number of a coefficients
409 :
410 : std::vector<uint32_t> m_NaCurrent; // The current number of a coefficients
411 :
412 : std::vector<uint32_t> m_Nb; // The latest user specified number of b coefficients
413 :
414 : std::vector<uint32_t> m_NbCurrent; // The current number of b coefficients
415 :
416 : eigenImage<float> m_as;
417 :
418 : eigenImage<float> m_bs;
419 :
420 : int m_nRegCycles{ 60 }; ///< How often to regularize each mode
421 :
422 : std::vector<int> m_regCounter; ///< Counters to track when this mode was last regularized
423 :
424 : std::vector<float> m_regScale; ///< The regularization scale factors for each mode
425 :
426 : std::vector<float> m_gainCals;
427 :
428 : std::vector<float> m_gainCalFacts;
429 :
430 : std::vector<float> m_taus;
431 :
432 : eigenImage<float> m_noiseParams;
433 :
434 : eigenImage<float> m_wfsavg;
435 : eigenImage<float> m_wfsmask;
436 : float m_counts{ 0 };
437 : float m_emg{ 1 };
438 : int m_npix{ 0 };
439 :
440 : int m_sinceChange{ -1 };
441 :
442 : std::string m_olPSDShmimName;
443 : std::string m_noisePSDShmimName;
444 : std::string m_clXferCurrentShmimName;
445 : std::string m_clXferSIShmimName;
446 : std::string m_clXferLPShmimName;
447 :
448 : std::string m_optGainShmimName;
449 : std::string m_optGainSIShmimName;
450 : std::string m_maxGainSIShmimName;
451 :
452 : std::string m_optGainLPShmimName;
453 : std::string m_maxGainLPShmimName;
454 :
455 : std::string m_modevarShmimName;
456 :
457 : IMAGE *m_olPSDStream{ nullptr }; ///< The ImageStreamIO shared memory buffer to publish the open loop PSDs
458 : IMAGE *m_noisePSDStream{ nullptr }; /**< The ImageStreamIO shared memory buffer to publish the noise
459 : PSDs (single value per mode)*/
460 : IMAGE *m_clXferCurrentStream{ nullptr }; ///< The ImageStreamIO shared memory buffer to publish the SI ETF
461 : IMAGE *m_clXferSIStream{ nullptr }; ///< The ImageStreamIO shared memory buffer to publish the SI ETF
462 : IMAGE *m_clXferLPStream{ nullptr }; ///< The ImageStreamIO shared memory buffer to publish the LP ETF
463 :
464 : IMAGE *m_optGainStream{ nullptr }; ///< The ImageStreamIO shared memory buffer to publish the optimal gains
465 :
466 : IMAGE *m_optGainSIStream{ nullptr }; ///< The ImageStreamIO shared memory buffer to publish the SI optimal gains
467 : IMAGE *m_maxGainSIStream{ nullptr }; ///< The ImageStreamIO shared memory buffer to publish the SI max gains
468 :
469 : IMAGE *m_optGainLPStream{ nullptr }; ///< The ImageStreamIO shared memory buffer to publish the LP optimal gains
470 : IMAGE *m_maxGainLPStream{ nullptr }; ///< The ImageStreamIO shared memory buffer to publish the LP max gains
471 :
472 : IMAGE *m_modevarStream{ nullptr }; ///< The ImageStreamIO shared memory buffer to publish the LP optimal gains
473 :
474 : public:
475 : /// Default c'tor.
476 : modalGainOpt();
477 :
478 : /// D'tor, declared and defined for noexcept.
479 0 : ~modalGainOpt() noexcept
480 0 : {
481 0 : }
482 :
483 : virtual void setupConfig();
484 :
485 : /// Implementation of loadConfig logic, separated for testing.
486 : /** This is called by loadConfig().
487 : */
488 : int loadConfigImpl( mx::app::appConfigurator &_config /**< [in] an application configuration
489 : from which to load values*/ );
490 :
491 : virtual void loadConfig();
492 :
493 : /// Startup function
494 : /**
495 : *
496 : */
497 : virtual int appStartup();
498 :
499 : /// Implementation of the FSM for modalGainOpt.
500 : /**
501 : * \returns 0 on no critical error
502 : * \returns -1 on an error requiring shutdown
503 : */
504 : virtual int appLogic();
505 :
506 : /// Shutdown the app.
507 : /**
508 : *
509 : */
510 : virtual int appShutdown();
511 :
512 : int allocatePCShmims();
513 :
514 : int allocate( const psdShmimT & ///< [in] tag to differentiate shmimMonitor parents.
515 : );
516 :
517 : int processImage( void *curr_src, ///< [in] pointer to the start of the current frame
518 : const psdShmimT & ///< [in] tag to differentiate shmimMonitor parents.
519 : );
520 :
521 : int allocate( const freqShmimT & ///< [in] tag to differentiate shmimMonitor parents.
522 : );
523 :
524 : int processImage( void *curr_src, ///< [in] pointer to the start of the current frame
525 : const freqShmimT & ///< [in] tag to differentiate shmimMonitor parents.
526 : );
527 :
528 : int allocate( const gainFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
529 : );
530 :
531 : int processImage( void *curr_src, ///< [in] pointer to the start of the current frame
532 : const gainFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
533 : );
534 :
535 : int allocate( const multFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
536 : );
537 :
538 : int processImage( void *curr_src, ///< [in] pointer to the start of the current frame
539 : const multFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
540 : );
541 :
542 : int allocate( const pcGainFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
543 : );
544 :
545 : int processImage( void *curr_src, ///< [in] pointer to the start of the current frame
546 : const pcGainFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
547 : );
548 :
549 : int allocate( const pcMultFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
550 : );
551 :
552 : int processImage( void *curr_src, ///< [in] pointer to the start of the current frame
553 : const pcMultFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
554 : );
555 :
556 : int allocate( const numpccoeffShmimT & ///< [in] tag to differentiate shmimMonitor parents.
557 : );
558 :
559 : int processImage( void *curr_src, ///< [in] pointer to the start of the current frame
560 : const numpccoeffShmimT & ///< [in] tag to differentiate shmimMonitor parents.
561 : );
562 :
563 : int allocate( const acoeffShmimT & ///< [in] tag to differentiate shmimMonitor parents.
564 : );
565 :
566 : int processImage( void *curr_src, ///< [in] pointer to the start of the current frame
567 : const acoeffShmimT & ///< [in] tag to differentiate shmimMonitor parents.
568 : );
569 :
570 : int allocate( const bcoeffShmimT & ///< [in] tag to differentiate shmimMonitor parents.
571 : );
572 :
573 : int processImage( void *curr_src, ///< [in] pointer to the start of the current frame
574 : const bcoeffShmimT & ///< [in] tag to differentiate shmimMonitor parents.
575 : );
576 :
577 : int allocate( const gainCalShmimT & ///< [in] tag to differentiate shmimMonitor parents.
578 : );
579 :
580 : int processImage( void *curr_src, ///< [in] pointer to the start of the current frame
581 : const gainCalShmimT & ///< [in] tag to differentiate shmimMonitor parents.
582 : );
583 :
584 : int allocate( const gainCalFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
585 : );
586 :
587 : int processImage( void *curr_src, ///< [in] pointer to the start of the current frame
588 : const gainCalFactShmimT & ///< [in] tag to differentiate shmimMonitor parents.
589 : );
590 :
591 : int allocate( const tauShmimT & ///< [in] tag to differentiate shmimMonitor parents.
592 : );
593 :
594 : int processImage( void *curr_src, ///< [in] pointer to the start of the current frame
595 : const tauShmimT & ///< [in] tag to differentiate shmimMonitor parents.
596 : );
597 :
598 : int allocate( const noiseShmimT & ///< [in] tag to differentiate shmimMonitor parents.
599 : );
600 :
601 : int processImage( void *curr_src, ///< [in] pointer to the start of the current frame
602 : const noiseShmimT & ///< [in] tag to differentiate shmimMonitor parents.
603 : );
604 :
605 : int allocate( const wfsavgShmimT & ///< [in] tag to differentiate shmimMonitor parents.
606 : );
607 :
608 : int processImage( void *curr_src, ///< [in] pointer to the start of the current frame
609 : const wfsavgShmimT & ///< [in] tag to differentiate shmimMonitor parents.
610 : );
611 :
612 : int allocate( const wfsmaskShmimT & ///< [in] tag to differentiate shmimMonitor parents.
613 : );
614 :
615 : int processImage( void *curr_src, ///< [in] pointer to the start of the current frame
616 : const wfsmaskShmimT & ///< [in] tag to differentiate shmimMonitor parents.
617 : );
618 :
619 : /// Check that all sizes and allocations have occurred
620 : int checkSizes();
621 :
622 : protected:
623 : /// Mutex for synchronizing updates.
624 : std::mutex m_goptMutex;
625 :
626 : /// Flag used to indicate to the goptThread that it should stop calculations ASAP
627 : bool m_updating{ false };
628 :
629 : /** \name Gain Optimization Thread
630 : *
631 : * @{
632 : */
633 : int m_goptThreadPrio{ 0 }; ///< Priority of the gain optimization thread.
634 :
635 : std::string m_goptThreadCpuset; ///< The cpuset to use for the gain optimization thread.
636 :
637 : std::thread m_goptThread; ///< The gain optimization thread.
638 :
639 : bool m_goptThreadInit{ true }; ///< Initialization flag for the gain optimization thread.
640 :
641 : pid_t m_goptThreadID{ 0 }; ///< gain optimization thread PID.
642 :
643 : pcf::IndiProperty m_goptThreadProp; ///< The property to hold the gain optimization thread details.
644 :
645 : sem_t m_goptSemaphore; ///< Semaphore used to synchronize the psdShmim thread and the gopt thread.
646 :
647 : float noisePSD( int n );
648 :
649 : /// Gain Optimization thread starter function
650 : static void goptThreadStart( modalGainOpt *p /**< [in] pointer to this */ );
651 :
652 : /// Gain optimization thread function
653 : /** Runs until m_shutdown is true.
654 : */
655 : void goptThreadExec();
656 :
657 : ///@}
658 :
659 : public:
660 : /** \name INDI
661 : * @{
662 : */
663 :
664 : pcf::IndiProperty m_indiP_autoUpdate;
665 : pcf::IndiProperty m_indiP_updateOnce;
666 : pcf::IndiProperty m_indiP_dump;
667 :
668 : pcf::IndiProperty m_indiP_opticalGain;
669 :
670 : pcf::IndiProperty m_indiP_gainGain;
671 :
672 : pcf::IndiProperty m_indiP_emg;
673 : pcf::IndiProperty m_indiP_psdTime;
674 : pcf::IndiProperty m_indiP_psdAvgTime;
675 : pcf::IndiProperty m_indiP_loop;
676 : pcf::IndiProperty m_indiP_siGain;
677 : pcf::IndiProperty m_indiP_siMult;
678 : pcf::IndiProperty m_indiP_pcGain;
679 : pcf::IndiProperty m_indiP_pcMult;
680 : pcf::IndiProperty m_indiP_pcOn;
681 :
682 : pcf::IndiProperty m_indiP_extrapOL;
683 :
684 : pcf::IndiProperty m_indiP_modesOn;
685 :
686 : pcf::IndiProperty m_indiP_opticalGainSource;
687 : pcf::IndiProperty m_indiP_opticalGainUpdate;
688 :
689 :
690 0 : INDI_NEWCALLBACK_DECL( modalGainOpt, m_indiP_autoUpdate );
691 0 : INDI_NEWCALLBACK_DECL( modalGainOpt, m_indiP_updateOnce );
692 0 : INDI_NEWCALLBACK_DECL( modalGainOpt, m_indiP_dump );
693 0 : INDI_NEWCALLBACK_DECL( modalGainOpt, m_indiP_opticalGain );
694 0 : INDI_NEWCALLBACK_DECL( modalGainOpt, m_indiP_gainGain );
695 0 : INDI_SETCALLBACK_DECL( modalGainOpt, m_indiP_emg );
696 0 : INDI_SETCALLBACK_DECL( modalGainOpt, m_indiP_psdTime );
697 0 : INDI_SETCALLBACK_DECL( modalGainOpt, m_indiP_psdAvgTime );
698 0 : INDI_SETCALLBACK_DECL( modalGainOpt, m_indiP_loop );
699 0 : INDI_SETCALLBACK_DECL( modalGainOpt, m_indiP_siGain );
700 0 : INDI_SETCALLBACK_DECL( modalGainOpt, m_indiP_siMult );
701 0 : INDI_SETCALLBACK_DECL( modalGainOpt, m_indiP_pcGain );
702 0 : INDI_SETCALLBACK_DECL( modalGainOpt, m_indiP_pcMult );
703 0 : INDI_SETCALLBACK_DECL( modalGainOpt, m_indiP_pcOn );
704 0 : INDI_NEWCALLBACK_DECL( modalGainOpt, m_indiP_extrapOL );
705 :
706 0 : INDI_SETCALLBACK_DECL( modalGainOpt, m_indiP_opticalGainSource );
707 0 : INDI_NEWCALLBACK_DECL( modalGainOpt, m_indiP_opticalGainUpdate);
708 :
709 :
710 : ///@}
711 : };
712 :
713 0 : modalGainOpt::modalGainOpt() : MagAOXApp( MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED )
714 : {
715 0 : psdShmimMonitorT::m_getExistingFirst = true;
716 0 : freqShmimMonitorT::m_getExistingFirst = true;
717 0 : gainFactShmimMonitorT::m_getExistingFirst = true;
718 0 : multFactShmimMonitorT::m_getExistingFirst = true;
719 0 : pcGainFactShmimMonitorT::m_getExistingFirst = true;
720 0 : pcMultFactShmimMonitorT::m_getExistingFirst = true;
721 0 : numpccoeffShmimMonitorT::m_getExistingFirst = true;
722 0 : acoeffShmimMonitorT::m_getExistingFirst = true;
723 0 : bcoeffShmimMonitorT::m_getExistingFirst = true;
724 0 : gainCalShmimMonitorT::m_getExistingFirst = true;
725 0 : gainCalFactShmimMonitorT::m_getExistingFirst = true;
726 0 : tauShmimMonitorT::m_getExistingFirst = true;
727 0 : noiseShmimMonitorT::m_getExistingFirst = true;
728 0 : wfsavgShmimMonitorT::m_getExistingFirst = true;
729 0 : wfsmaskShmimMonitorT::m_getExistingFirst = true;
730 :
731 0 : return;
732 0 : }
733 :
734 0 : void modalGainOpt::setupConfig()
735 : {
736 0 : config.add( "loop.number",
737 : "",
738 : "loop.number",
739 : argType::Required,
740 : "loop",
741 : "number",
742 : false,
743 : "int",
744 : "The number of the loop. Used to set shmim names, as in aolN_mgainfact." );
745 :
746 0 : config.add( "loop.name",
747 : "",
748 : "loop.name",
749 : argType::Required,
750 : "loop",
751 : "name",
752 : false,
753 : "string",
754 : "The name of the loop control INDI device name." );
755 :
756 0 : config.add( "loop.psdDev",
757 : "",
758 : "loop.psdDev",
759 : argType::Required,
760 : "loop",
761 : "psdDev",
762 : false,
763 : "string",
764 : "The INDI device name of the PSD calculator. Defaults to aolN_modevalPSDs where N is loop.number." );
765 :
766 0 : config.add( "loop.autoUpdate",
767 : "",
768 : "loop.autoUpdate",
769 : argType::Required,
770 : "loop",
771 : "autoUpdate",
772 : false,
773 : "bool",
774 : "Flag controlling whether the gains are auto updated. Also settable via INDI." );
775 :
776 0 : config.add( "loop.gainGain",
777 : "",
778 : "loop.gainGain",
779 : argType::Required,
780 : "loop",
781 : "gainGain",
782 : false,
783 : "float",
784 : "The gain to use for closed-loop gain updates. Default is 0.1" );
785 :
786 0 : SHMIMMONITORT_SETUP_CONFIG( psdShmimMonitorT, config );
787 0 : SHMIMMONITORT_SETUP_CONFIG( freqShmimMonitorT, config );
788 0 : SHMIMMONITORT_SETUP_CONFIG( gainFactShmimMonitorT, config );
789 0 : SHMIMMONITORT_SETUP_CONFIG( multFactShmimMonitorT, config );
790 0 : SHMIMMONITORT_SETUP_CONFIG( pcGainFactShmimMonitorT, config );
791 0 : SHMIMMONITORT_SETUP_CONFIG( pcMultFactShmimMonitorT, config );
792 0 : SHMIMMONITORT_SETUP_CONFIG( numpccoeffShmimMonitorT, config );
793 0 : SHMIMMONITORT_SETUP_CONFIG( acoeffShmimMonitorT, config );
794 0 : SHMIMMONITORT_SETUP_CONFIG( bcoeffShmimMonitorT, config );
795 0 : SHMIMMONITORT_SETUP_CONFIG( gainCalShmimMonitorT, config );
796 0 : SHMIMMONITORT_SETUP_CONFIG( gainCalFactShmimMonitorT, config );
797 0 : SHMIMMONITORT_SETUP_CONFIG( tauShmimMonitorT, config );
798 0 : SHMIMMONITORT_SETUP_CONFIG( noiseShmimMonitorT, config );
799 0 : SHMIMMONITORT_SETUP_CONFIG( wfsavgShmimMonitorT, config );
800 0 : SHMIMMONITORT_SETUP_CONFIG( wfsmaskShmimMonitorT, config );
801 : }
802 :
803 0 : int modalGainOpt::loadConfigImpl( mx::app::appConfigurator &_config )
804 : {
805 0 : _config( m_loopNum, "loop.number" );
806 0 : _config( m_loopName, "loop.name" );
807 0 : _config( m_autoUpdate, "loop.autoUpdate" );
808 0 : _config( m_autoUpdate, "loop.gainGain" );
809 :
810 : char shmim[1024];
811 :
812 0 : _config( m_psdDevice, "loop.psdDev" );
813 :
814 0 : snprintf( shmim, sizeof( shmim ), "aol%d_clpsds", m_loopNum );
815 0 : psdShmimMonitorT::m_shmimName = shmim;
816 0 : SHMIMMONITORT_LOAD_CONFIG( psdShmimMonitorT, _config );
817 :
818 0 : snprintf( shmim, sizeof( shmim ), "aol%d_freq", m_loopNum );
819 0 : freqShmimMonitorT::m_shmimName = shmim;
820 0 : SHMIMMONITORT_LOAD_CONFIG( freqShmimMonitorT, _config );
821 :
822 0 : snprintf( shmim, sizeof( shmim ), "aol%d_mgainfact", m_loopNum );
823 0 : gainFactShmimMonitorT::m_shmimName = shmim;
824 0 : SHMIMMONITORT_LOAD_CONFIG( gainFactShmimMonitorT, _config );
825 :
826 0 : snprintf( shmim, sizeof( shmim ), "aol%d_mmultfact", m_loopNum );
827 0 : multFactShmimMonitorT::m_shmimName = shmim;
828 0 : SHMIMMONITORT_LOAD_CONFIG( multFactShmimMonitorT, _config );
829 :
830 0 : snprintf( shmim, sizeof( shmim ), "aol%d_mpcgainfact", m_loopNum );
831 0 : pcGainFactShmimMonitorT::m_shmimName = shmim;
832 0 : SHMIMMONITORT_LOAD_CONFIG( pcGainFactShmimMonitorT, _config );
833 :
834 0 : snprintf( shmim, sizeof( shmim ), "aol%d_mpcmultfact", m_loopNum );
835 0 : pcMultFactShmimMonitorT::m_shmimName = shmim;
836 0 : SHMIMMONITORT_LOAD_CONFIG( pcMultFactShmimMonitorT, _config );
837 :
838 0 : snprintf( shmim, sizeof( shmim ), "aol%d_numpccoeff", m_loopNum );
839 0 : numpccoeffShmimMonitorT::m_shmimName = shmim;
840 0 : SHMIMMONITORT_LOAD_CONFIG( numpccoeffShmimMonitorT, _config );
841 :
842 0 : snprintf( shmim, sizeof( shmim ), "aol%d_acoeff", m_loopNum );
843 0 : acoeffShmimMonitorT::m_shmimName = shmim;
844 0 : SHMIMMONITORT_LOAD_CONFIG( acoeffShmimMonitorT, _config );
845 :
846 0 : snprintf( shmim, sizeof( shmim ), "aol%d_bcoeff", m_loopNum );
847 0 : bcoeffShmimMonitorT::m_shmimName = shmim;
848 0 : SHMIMMONITORT_LOAD_CONFIG( bcoeffShmimMonitorT, _config );
849 :
850 0 : snprintf( shmim, sizeof( shmim ), "aol%d_mgaincal", m_loopNum );
851 0 : gainCalShmimMonitorT::m_shmimName = shmim;
852 0 : SHMIMMONITORT_LOAD_CONFIG( gainCalShmimMonitorT, _config );
853 :
854 0 : snprintf( shmim, sizeof( shmim ), "aol%d_mgaincalfact", m_loopNum );
855 0 : gainCalFactShmimMonitorT::m_shmimName = shmim;
856 0 : SHMIMMONITORT_LOAD_CONFIG( gainCalFactShmimMonitorT, _config );
857 :
858 0 : snprintf( shmim, sizeof( shmim ), "aol%d_looptau", m_loopNum );
859 0 : tauShmimMonitorT::m_shmimName = shmim;
860 0 : SHMIMMONITORT_LOAD_CONFIG( tauShmimMonitorT, _config );
861 :
862 0 : snprintf( shmim, sizeof( shmim ), "aol%d_mnoiseparam", m_loopNum );
863 0 : noiseShmimMonitorT::m_shmimName = shmim;
864 0 : SHMIMMONITORT_LOAD_CONFIG( noiseShmimMonitorT, _config );
865 :
866 0 : snprintf( shmim, sizeof( shmim ), "aol%d_wfsavg", m_loopNum );
867 0 : wfsavgShmimMonitorT::m_shmimName = shmim;
868 0 : SHMIMMONITORT_LOAD_CONFIG( wfsavgShmimMonitorT, _config );
869 :
870 0 : snprintf( shmim, sizeof( shmim ), "aol%d_wfsmask", m_loopNum );
871 0 : wfsmaskShmimMonitorT::m_shmimName = shmim;
872 0 : SHMIMMONITORT_LOAD_CONFIG( wfsmaskShmimMonitorT, _config );
873 :
874 0 : snprintf( shmim, sizeof( shmim ), "aol%d_olpsds", m_loopNum );
875 0 : m_olPSDShmimName = shmim;
876 :
877 0 : snprintf( shmim, sizeof( shmim ), "aol%d_noisepsds", m_loopNum );
878 0 : m_noisePSDShmimName = shmim;
879 :
880 0 : snprintf( shmim, sizeof( shmim ), "aol%d_clxferCurrent", m_loopNum );
881 0 : m_clXferCurrentShmimName = shmim;
882 :
883 0 : snprintf( shmim, sizeof( shmim ), "aol%d_clxferSI", m_loopNum );
884 0 : m_clXferSIShmimName = shmim;
885 :
886 0 : snprintf( shmim, sizeof( shmim ), "aol%d_clxferLP", m_loopNum );
887 0 : m_clXferLPShmimName = shmim;
888 :
889 0 : snprintf( shmim, sizeof( shmim ), "aol%d_mgainoptimal", m_loopNum );
890 0 : m_optGainShmimName = shmim;
891 :
892 0 : snprintf( shmim, sizeof( shmim ), "aol%d_mgainoptimalSI", m_loopNum );
893 0 : m_optGainSIShmimName = shmim;
894 :
895 0 : snprintf( shmim, sizeof( shmim ), "aol%d_mgainmaxSI", m_loopNum );
896 0 : m_maxGainSIShmimName = shmim;
897 :
898 0 : snprintf( shmim, sizeof( shmim ), "aol%d_mgainoptimalLP", m_loopNum );
899 0 : m_optGainLPShmimName = shmim;
900 :
901 0 : snprintf( shmim, sizeof( shmim ), "aol%d_mgainmaxLP", m_loopNum );
902 0 : m_maxGainLPShmimName = shmim;
903 :
904 0 : snprintf( shmim, sizeof( shmim ), "aol%d_mmodevar", m_loopNum );
905 0 : m_modevarShmimName = shmim;
906 :
907 0 : return 0;
908 : }
909 :
910 0 : void modalGainOpt::loadConfig()
911 : {
912 0 : loadConfigImpl( config );
913 0 : }
914 :
915 0 : int modalGainOpt::appStartup()
916 : {
917 0 : SHMIMMONITORT_APP_STARTUP( psdShmimMonitorT );
918 0 : SHMIMMONITORT_APP_STARTUP( freqShmimMonitorT );
919 0 : SHMIMMONITORT_APP_STARTUP( gainFactShmimMonitorT );
920 0 : SHMIMMONITORT_APP_STARTUP( multFactShmimMonitorT );
921 0 : SHMIMMONITORT_APP_STARTUP( pcGainFactShmimMonitorT );
922 0 : SHMIMMONITORT_APP_STARTUP( pcMultFactShmimMonitorT );
923 0 : SHMIMMONITORT_APP_STARTUP( numpccoeffShmimMonitorT );
924 0 : SHMIMMONITORT_APP_STARTUP( acoeffShmimMonitorT );
925 0 : SHMIMMONITORT_APP_STARTUP( bcoeffShmimMonitorT );
926 0 : SHMIMMONITORT_APP_STARTUP( gainCalShmimMonitorT );
927 0 : SHMIMMONITORT_APP_STARTUP( gainCalFactShmimMonitorT );
928 0 : SHMIMMONITORT_APP_STARTUP( tauShmimMonitorT );
929 0 : SHMIMMONITORT_APP_STARTUP( noiseShmimMonitorT );
930 0 : SHMIMMONITORT_APP_STARTUP( wfsavgShmimMonitorT );
931 0 : SHMIMMONITORT_APP_STARTUP( wfsmaskShmimMonitorT );
932 :
933 0 : CREATE_REG_INDI_NEW_TOGGLESWITCH( m_indiP_autoUpdate, "update_auto" );
934 0 : CREATE_REG_INDI_NEW_REQUESTSWITCH( m_indiP_updateOnce, "update_once" );
935 0 : CREATE_REG_INDI_NEW_REQUESTSWITCH( m_indiP_dump, "update_dump" );
936 :
937 0 : CREATE_REG_INDI_NEW_NUMBERF(
938 : m_indiP_opticalGain, "opticalGain", 0, 1, 0.01, "%0.01f", "Optical Gain", "Gain Opt." );
939 0 : CREATE_REG_INDI_NEW_NUMBERF( m_indiP_gainGain, "gainGain", 0, 1, 0.01, "%0.01f", "Gain Gain", "Gain Opt." );
940 :
941 0 : REG_INDI_SETPROP( m_indiP_emg, m_wfsDevice, "emgain" );
942 0 : REG_INDI_SETPROP( m_indiP_psdTime, m_psdDevice, "psdTime" );
943 0 : REG_INDI_SETPROP( m_indiP_psdAvgTime, m_psdDevice, "psdAvgTime" );
944 0 : REG_INDI_SETPROP( m_indiP_loop, m_loopName, "loop_state" );
945 0 : REG_INDI_SETPROP( m_indiP_siGain, m_loopName, "loop_gain" );
946 0 : REG_INDI_SETPROP( m_indiP_siMult, m_loopName, "loop_multcoeff" );
947 0 : REG_INDI_SETPROP( m_indiP_pcGain, m_loopName, "loop_pcgain" );
948 0 : REG_INDI_SETPROP( m_indiP_pcMult, m_loopName, "loop_pcmultcoeff" );
949 0 : REG_INDI_SETPROP( m_indiP_pcOn, m_loopName, "loop_pcOn" );
950 :
951 0 : CREATE_REG_INDI_NEW_TOGGLESWITCH( m_indiP_extrapOL, "extrapOL" );
952 :
953 0 : CREATE_REG_INDI_RO_NUMBER(m_indiP_modesOn, "num_modes", "number of modes", "Gain Opt.");
954 0 : indi::addNumberElement(m_indiP_modesOn, "current", 0, 2400, 1, "%d", "Applied Modes");
955 0 : indi::addNumberElement(m_indiP_modesOn, "integrator", 0, 2400, 1, "%d", "SI optimal");
956 0 : indi::addNumberElement(m_indiP_modesOn, "predictor", 0, 2400, 1, "%d", "LP optimal");
957 :
958 0 : REG_INDI_SETPROP( m_indiP_opticalGainSource, m_opticalGainDevice, m_opticalGainProperty );
959 :
960 0 : CREATE_REG_INDI_NEW_TOGGLESWITCH(m_indiP_opticalGainUpdate, "track_optical_gain");
961 :
962 0 : if( sem_init( &m_goptSemaphore, 0, 0 ) < 0 )
963 : {
964 0 : return log<software_critical, -1>( { __FILE__, __LINE__, errno, 0, "Initializing gopt semaphore" } );
965 : }
966 :
967 0 : XWCAPP_THREAD_START( m_goptThread,
968 : m_goptThreadInit,
969 : m_goptThreadID,
970 : m_goptThreadProp,
971 : m_goptThreadPrio,
972 : m_goptThreadCpuset,
973 : "gainopt",
974 : goptThreadStart );
975 :
976 0 : state( stateCodes::OPERATING );
977 0 : return 0;
978 : }
979 :
980 0 : int modalGainOpt::appLogic()
981 : {
982 0 : SHMIMMONITORT_APP_LOGIC( psdShmimMonitorT );
983 0 : SHMIMMONITORT_APP_LOGIC( freqShmimMonitorT );
984 0 : SHMIMMONITORT_APP_LOGIC( gainFactShmimMonitorT );
985 0 : SHMIMMONITORT_APP_LOGIC( multFactShmimMonitorT );
986 0 : SHMIMMONITORT_APP_LOGIC( pcGainFactShmimMonitorT );
987 0 : SHMIMMONITORT_APP_LOGIC( pcMultFactShmimMonitorT );
988 0 : SHMIMMONITORT_APP_LOGIC( numpccoeffShmimMonitorT );
989 0 : SHMIMMONITORT_APP_LOGIC( acoeffShmimMonitorT );
990 0 : SHMIMMONITORT_APP_LOGIC( bcoeffShmimMonitorT );
991 0 : SHMIMMONITORT_APP_LOGIC( gainCalShmimMonitorT );
992 0 : SHMIMMONITORT_APP_LOGIC( gainCalFactShmimMonitorT );
993 0 : SHMIMMONITORT_APP_LOGIC( tauShmimMonitorT );
994 0 : SHMIMMONITORT_APP_LOGIC( noiseShmimMonitorT );
995 0 : SHMIMMONITORT_APP_LOGIC( wfsavgShmimMonitorT );
996 0 : SHMIMMONITORT_APP_LOGIC( wfsmaskShmimMonitorT );
997 :
998 0 : XWCAPP_THREAD_CHECK( m_goptThread, "gainopt" );
999 :
1000 0 : SHMIMMONITORT_UPDATE_INDI( psdShmimMonitorT );
1001 0 : SHMIMMONITORT_UPDATE_INDI( freqShmimMonitorT );
1002 0 : SHMIMMONITORT_UPDATE_INDI( gainFactShmimMonitorT );
1003 0 : SHMIMMONITORT_UPDATE_INDI( multFactShmimMonitorT );
1004 0 : SHMIMMONITORT_UPDATE_INDI( pcGainFactShmimMonitorT );
1005 0 : SHMIMMONITORT_UPDATE_INDI( pcMultFactShmimMonitorT );
1006 0 : SHMIMMONITORT_UPDATE_INDI( numpccoeffShmimMonitorT );
1007 0 : SHMIMMONITORT_UPDATE_INDI( acoeffShmimMonitorT );
1008 0 : SHMIMMONITORT_UPDATE_INDI( bcoeffShmimMonitorT );
1009 0 : SHMIMMONITORT_UPDATE_INDI( gainCalShmimMonitorT );
1010 0 : SHMIMMONITORT_UPDATE_INDI( gainCalFactShmimMonitorT );
1011 0 : SHMIMMONITORT_UPDATE_INDI( tauShmimMonitorT );
1012 0 : SHMIMMONITORT_UPDATE_INDI( noiseShmimMonitorT );
1013 0 : SHMIMMONITORT_UPDATE_INDI( wfsavgShmimMonitorT );
1014 0 : SHMIMMONITORT_UPDATE_INDI( wfsmaskShmimMonitorT );
1015 :
1016 0 : if( m_autoUpdate )
1017 : {
1018 0 : updateSwitchIfChanged( m_indiP_autoUpdate, "toggle", pcf::IndiElement::On, INDI_OK );
1019 : }
1020 : else
1021 : {
1022 0 : updateSwitchIfChanged( m_indiP_autoUpdate, "toggle", pcf::IndiElement::Off, INDI_IDLE );
1023 : }
1024 :
1025 0 : if( m_updateOnce )
1026 : {
1027 0 : updateSwitchIfChanged( m_indiP_updateOnce, "request", pcf::IndiElement::On, INDI_OK );
1028 : }
1029 : else
1030 : {
1031 0 : updateSwitchIfChanged( m_indiP_updateOnce, "request", pcf::IndiElement::Off, INDI_IDLE );
1032 : }
1033 :
1034 0 : if( m_dump )
1035 : {
1036 0 : updateSwitchIfChanged( m_indiP_dump, "request", pcf::IndiElement::On, INDI_OK );
1037 : }
1038 : else
1039 : {
1040 0 : updateSwitchIfChanged( m_indiP_dump, "request", pcf::IndiElement::Off, INDI_IDLE );
1041 : }
1042 :
1043 0 : if( m_opticalGainUpdate )
1044 : {
1045 0 : updateSwitchIfChanged( m_indiP_opticalGainUpdate, "toggle", pcf::IndiElement::On, INDI_OK );
1046 : }
1047 : else
1048 : {
1049 0 : updateSwitchIfChanged( m_indiP_opticalGainUpdate, "toggle", pcf::IndiElement::Off, INDI_IDLE );
1050 : }
1051 :
1052 0 : updatesIfChanged<float>( m_indiP_opticalGain, { "current", "target" }, { m_opticalGain, m_opticalGain } );
1053 :
1054 0 : updatesIfChanged<float>( m_indiP_gainGain, { "current", "target" }, { m_gainGain, m_gainGain } );
1055 :
1056 0 : if(m_extrapOL == 0)
1057 : {
1058 0 : updateSwitchIfChanged(m_indiP_extrapOL, "toggle", pcf::IndiElement::Off);
1059 : }
1060 : else
1061 : {
1062 0 : updateSwitchIfChanged(m_indiP_extrapOL, "toggle", pcf::IndiElement::On);
1063 : }
1064 :
1065 0 : updatesIfChanged<int>(m_indiP_modesOn, {"current","integrator","predictor"}, {m_modesOn, m_modesOnSI, m_modesOnLP});
1066 :
1067 :
1068 0 : return 0;
1069 : }
1070 :
1071 0 : int modalGainOpt::appShutdown()
1072 : {
1073 0 : XWCAPP_THREAD_STOP( m_goptThread );
1074 :
1075 0 : SHMIMMONITORT_APP_SHUTDOWN( psdShmimMonitorT );
1076 0 : SHMIMMONITORT_APP_SHUTDOWN( freqShmimMonitorT );
1077 0 : SHMIMMONITORT_APP_SHUTDOWN( gainFactShmimMonitorT );
1078 0 : SHMIMMONITORT_APP_SHUTDOWN( multFactShmimMonitorT );
1079 0 : SHMIMMONITORT_APP_SHUTDOWN( pcGainFactShmimMonitorT );
1080 0 : SHMIMMONITORT_APP_SHUTDOWN( pcMultFactShmimMonitorT );
1081 0 : SHMIMMONITORT_APP_SHUTDOWN( numpccoeffShmimMonitorT );
1082 0 : SHMIMMONITORT_APP_SHUTDOWN( acoeffShmimMonitorT );
1083 0 : SHMIMMONITORT_APP_SHUTDOWN( bcoeffShmimMonitorT );
1084 0 : SHMIMMONITORT_APP_SHUTDOWN( gainCalShmimMonitorT );
1085 0 : SHMIMMONITORT_APP_SHUTDOWN( gainCalFactShmimMonitorT );
1086 0 : SHMIMMONITORT_APP_SHUTDOWN( tauShmimMonitorT );
1087 0 : SHMIMMONITORT_APP_SHUTDOWN( noiseShmimMonitorT );
1088 0 : SHMIMMONITORT_APP_SHUTDOWN( wfsavgShmimMonitorT );
1089 0 : SHMIMMONITORT_APP_SHUTDOWN( wfsmaskShmimMonitorT );
1090 :
1091 0 : if( m_olPSDStream != nullptr )
1092 : {
1093 0 : ImageStreamIO_destroyIm( m_olPSDStream );
1094 0 : free( m_olPSDStream );
1095 0 : m_olPSDStream = nullptr;
1096 :
1097 0 : ImageStreamIO_destroyIm( m_noisePSDStream );
1098 0 : free( m_noisePSDStream );
1099 0 : m_noisePSDStream = nullptr;
1100 :
1101 0 : ImageStreamIO_destroyIm( m_clXferCurrentStream );
1102 0 : free( m_clXferCurrentStream );
1103 0 : m_clXferCurrentStream = nullptr;
1104 :
1105 0 : ImageStreamIO_destroyIm( m_clXferSIStream );
1106 0 : free( m_clXferSIStream );
1107 0 : m_clXferSIStream = nullptr;
1108 :
1109 0 : ImageStreamIO_destroyIm( m_clXferLPStream );
1110 0 : free( m_clXferLPStream );
1111 0 : m_clXferLPStream = nullptr;
1112 : }
1113 :
1114 0 : if( m_optGainStream != nullptr )
1115 : {
1116 0 : ImageStreamIO_destroyIm( m_optGainStream );
1117 0 : free( m_optGainStream );
1118 0 : m_optGainStream = nullptr;
1119 :
1120 0 : ImageStreamIO_destroyIm( m_optGainSIStream );
1121 0 : free( m_optGainSIStream );
1122 0 : m_optGainSIStream = nullptr;
1123 :
1124 0 : ImageStreamIO_destroyIm( m_maxGainSIStream );
1125 0 : free( m_maxGainSIStream );
1126 0 : m_maxGainSIStream = nullptr;
1127 :
1128 0 : ImageStreamIO_destroyIm( m_optGainLPStream );
1129 0 : free( m_optGainLPStream );
1130 0 : m_optGainLPStream = nullptr;
1131 :
1132 0 : ImageStreamIO_destroyIm( m_maxGainLPStream );
1133 0 : free( m_maxGainLPStream );
1134 0 : m_maxGainLPStream = nullptr;
1135 :
1136 0 : ImageStreamIO_destroyIm( m_modevarStream );
1137 0 : free( m_modevarStream );
1138 0 : m_modevarStream = nullptr;
1139 : }
1140 :
1141 0 : return 0;
1142 : }
1143 :
1144 0 : int modalGainOpt::allocatePCShmims()
1145 : {
1146 : // mutex should be locked before calling this
1147 :
1148 0 : if( numpccoeffShmimMonitorT::m_smState != dev::shmimMonitorState::connected ||
1149 0 : numpccoeffShmimMonitorT::m_width != m_nModes || numpccoeffShmimMonitorT::m_height != 2 )
1150 : {
1151 0 : mx::improc::eigenImage<uint32_t> Npc( m_nModes, 2 );
1152 0 : Npc.setConstant( m_defaultNCoeff );
1153 :
1154 0 : if( numpccoeffShmimMonitorT::create( m_nModes, 2, 1, _DATATYPE_UINT32, Npc.data() ) != 0 )
1155 : {
1156 0 : return log<software_error, -1>( { __FILE__, __LINE__, "error creating numpccoeffShmim" } );
1157 : }
1158 :
1159 : MGO_BREADCRUMB;
1160 :
1161 0 : std::cerr << "created numppccoeff shmim\n";
1162 0 : }
1163 :
1164 0 : if( acoeffShmimMonitorT::m_smState != dev::shmimMonitorState::connected ||
1165 0 : acoeffShmimMonitorT::m_width != m_maxNCoeff + 1 || acoeffShmimMonitorT::m_height != m_nModes )
1166 : {
1167 0 : if( acoeffShmimMonitorT::create( m_maxNCoeff + 1, m_nModes, 1, _DATATYPE_FLOAT ) != 0 )
1168 : {
1169 0 : return log<software_error, -1>( { __FILE__, __LINE__, "error creating acoeffShmim" } );
1170 : }
1171 :
1172 0 : std::cerr << "created acoeff shmim\n";
1173 : }
1174 :
1175 0 : if( bcoeffShmimMonitorT::m_smState != dev::shmimMonitorState::connected ||
1176 0 : bcoeffShmimMonitorT::m_width != m_maxNCoeff || bcoeffShmimMonitorT::m_height != m_nModes )
1177 : {
1178 0 : if( bcoeffShmimMonitorT::create( m_maxNCoeff + 1, m_nModes, 1, _DATATYPE_FLOAT ) != 0 )
1179 : {
1180 0 : return log<software_error, -1>( { __FILE__, __LINE__, "error creating bcoeffShmim" } );
1181 : }
1182 :
1183 0 : std::cerr << "created bcoeff shmim\n";
1184 : }
1185 :
1186 0 : if( pcGainFactShmimMonitorT::m_smState != dev::shmimMonitorState::connected ||
1187 0 : pcGainFactShmimMonitorT::m_width != m_nModes || pcGainFactShmimMonitorT::m_height != 1 )
1188 : {
1189 0 : if( pcGainFactShmimMonitorT::create( m_nModes, 1, 1, _DATATYPE_FLOAT ) != 0 )
1190 : {
1191 0 : return log<software_error, -1>( { __FILE__, __LINE__, "error creating pcGainFactShmim" } );
1192 : }
1193 :
1194 0 : std::cerr << "created pcGainFact shmim\n";
1195 : }
1196 :
1197 0 : if( pcMultFactShmimMonitorT::m_smState != dev::shmimMonitorState::connected ||
1198 0 : pcMultFactShmimMonitorT::m_width != m_nModes || pcMultFactShmimMonitorT::m_height != 1 )
1199 : {
1200 0 : if( pcMultFactShmimMonitorT::create( m_nModes, 1, 1, _DATATYPE_FLOAT ) != 0 )
1201 : {
1202 0 : return log<software_error, -1>( { __FILE__, __LINE__, "error creating pcMultFactShmim" } );
1203 : }
1204 :
1205 0 : std::cerr << "created pcMultFact shmim\n";
1206 : }
1207 :
1208 0 : return 0;
1209 : }
1210 :
1211 0 : int modalGainOpt::allocate( const psdShmimT &dummy )
1212 : {
1213 : static_cast<void>( dummy );
1214 :
1215 0 : m_updating = true;
1216 0 : std::lock_guard<std::mutex> lock( m_goptMutex );
1217 :
1218 0 : m_updating = true;
1219 :
1220 0 : m_nFreq = psdShmimMonitorT::m_width;
1221 0 : m_nModes = psdShmimMonitorT::m_height;
1222 :
1223 0 : m_clPSDs.resize( m_nFreq, m_nModes );
1224 :
1225 0 : m_clXferCurrent.resize( m_nFreq, m_nModes );
1226 0 : m_clXferSI.resize( m_nFreq, m_nModes );
1227 0 : m_clXferLP.resize( m_nFreq, m_nModes );
1228 :
1229 0 : m_olPSDs.resize( m_nModes );
1230 0 : m_nPSDs.resize( m_nModes );
1231 :
1232 0 : for( size_t n = 0; n < m_olPSDs.size(); ++n )
1233 : {
1234 0 : m_olPSDs[n].resize( m_nFreq );
1235 0 : m_nPSDs[n].resize( m_nFreq );
1236 : }
1237 :
1238 0 : m_modeVarOL.resize( m_nModes );
1239 :
1240 0 : m_optGainSI.resize( m_nModes );
1241 0 : m_gmaxSI.resize( m_nModes );
1242 0 : m_modeVarSI.resize( m_nModes );
1243 0 : m_timesOnSI.resize( m_nModes, 5 );
1244 :
1245 :
1246 0 : m_optGainLP.resize( m_nModes );
1247 0 : m_modeVarLP.resize( m_nModes );
1248 0 : m_timesOnLP.resize( m_nModes, 5 );
1249 :
1250 0 : if( m_olPSDStream != nullptr &&
1251 0 : ( m_olPSDStream->md->size[0] != m_nFreq || m_olPSDStream->md->size[1] != m_nModes ) )
1252 : {
1253 0 : ImageStreamIO_destroyIm( m_olPSDStream );
1254 0 : free( m_olPSDStream );
1255 0 : m_olPSDStream = nullptr;
1256 :
1257 0 : ImageStreamIO_destroyIm( m_noisePSDStream );
1258 0 : free( m_noisePSDStream );
1259 0 : m_noisePSDStream = nullptr;
1260 :
1261 0 : ImageStreamIO_destroyIm( m_clXferCurrentStream );
1262 0 : free( m_clXferCurrentStream );
1263 0 : m_clXferCurrentStream = nullptr;
1264 :
1265 0 : ImageStreamIO_destroyIm( m_clXferSIStream );
1266 0 : free( m_clXferSIStream );
1267 0 : m_clXferSIStream = nullptr;
1268 :
1269 0 : ImageStreamIO_destroyIm( m_clXferLPStream );
1270 0 : free( m_clXferLPStream );
1271 0 : m_clXferLPStream = nullptr;
1272 : }
1273 :
1274 0 : if( m_olPSDStream == nullptr )
1275 : {
1276 0 : m_olPSDStream = static_cast<IMAGE *>( malloc( sizeof( IMAGE ) ) );
1277 : uint32_t imsize[3];
1278 :
1279 0 : imsize[0] = m_nFreq;
1280 0 : imsize[1] = m_nModes;
1281 0 : imsize[2] = 1;
1282 0 : ImageStreamIO_createIm_gpu( m_olPSDStream,
1283 : m_olPSDShmimName.c_str(),
1284 : 3,
1285 : imsize,
1286 0 : psdShmimMonitorT::m_dataType,
1287 : -1,
1288 : 1,
1289 : IMAGE_NB_SEMAPHORE,
1290 : 0,
1291 : CIRCULAR_BUFFER | ZAXIS_TEMPORAL,
1292 : 0 );
1293 :
1294 0 : m_olPSDStream->md->cnt0 = 0;
1295 0 : m_olPSDStream->md->cnt1 = 0;
1296 :
1297 0 : m_noisePSDStream = static_cast<IMAGE *>( malloc( sizeof( IMAGE ) ) );
1298 :
1299 0 : ImageStreamIO_createIm_gpu( m_noisePSDStream,
1300 : m_noisePSDShmimName.c_str(),
1301 : 3,
1302 : imsize,
1303 0 : psdShmimMonitorT::m_dataType,
1304 : -1,
1305 : 1,
1306 : IMAGE_NB_SEMAPHORE,
1307 : 0,
1308 : CIRCULAR_BUFFER | ZAXIS_TEMPORAL,
1309 : 0 );
1310 :
1311 0 : m_noisePSDStream->md->cnt0 = 0;
1312 0 : m_noisePSDStream->md->cnt1 = 0;
1313 :
1314 0 : m_clXferCurrentStream = static_cast<IMAGE *>( malloc( sizeof( IMAGE ) ) );
1315 :
1316 0 : ImageStreamIO_createIm_gpu( m_clXferCurrentStream,
1317 : m_clXferCurrentShmimName.c_str(),
1318 : 3,
1319 : imsize,
1320 0 : psdShmimMonitorT::m_dataType,
1321 : -1,
1322 : 1,
1323 : IMAGE_NB_SEMAPHORE,
1324 : 0,
1325 : CIRCULAR_BUFFER | ZAXIS_TEMPORAL,
1326 : 0 );
1327 :
1328 0 : m_clXferCurrentStream->md->cnt0 = 0;
1329 0 : m_clXferCurrentStream->md->cnt1 = 0;
1330 :
1331 0 : m_clXferSIStream = static_cast<IMAGE *>( malloc( sizeof( IMAGE ) ) );
1332 :
1333 0 : ImageStreamIO_createIm_gpu( m_clXferSIStream,
1334 : m_clXferSIShmimName.c_str(),
1335 : 3,
1336 : imsize,
1337 0 : psdShmimMonitorT::m_dataType,
1338 : -1,
1339 : 1,
1340 : IMAGE_NB_SEMAPHORE,
1341 : 0,
1342 : CIRCULAR_BUFFER | ZAXIS_TEMPORAL,
1343 : 0 );
1344 :
1345 0 : m_clXferSIStream->md->cnt0 = 0;
1346 0 : m_clXferSIStream->md->cnt1 = 0;
1347 :
1348 0 : m_clXferLPStream = static_cast<IMAGE *>( malloc( sizeof( IMAGE ) ) );
1349 :
1350 0 : ImageStreamIO_createIm_gpu( m_clXferLPStream,
1351 : m_clXferLPShmimName.c_str(),
1352 : 3,
1353 : imsize,
1354 0 : psdShmimMonitorT::m_dataType,
1355 : -1,
1356 : 1,
1357 : IMAGE_NB_SEMAPHORE,
1358 : 0,
1359 : CIRCULAR_BUFFER | ZAXIS_TEMPORAL,
1360 : 0 );
1361 :
1362 0 : m_clXferLPStream->md->cnt0 = 0;
1363 0 : m_clXferLPStream->md->cnt1 = 0;
1364 : }
1365 :
1366 0 : if( m_optGainStream != nullptr &&
1367 0 : ( m_optGainStream->md->size[0] != psdShmimMonitorT::m_height || m_optGainStream->md->size[1] != 1 ) )
1368 : {
1369 0 : ImageStreamIO_destroyIm( m_optGainStream );
1370 0 : free( m_optGainStream );
1371 0 : m_optGainStream = nullptr;
1372 :
1373 0 : ImageStreamIO_destroyIm( m_optGainSIStream );
1374 0 : free( m_optGainSIStream );
1375 0 : m_optGainSIStream = nullptr;
1376 :
1377 0 : ImageStreamIO_destroyIm( m_maxGainSIStream );
1378 0 : free( m_maxGainSIStream );
1379 0 : m_maxGainSIStream = nullptr;
1380 :
1381 0 : ImageStreamIO_destroyIm( m_optGainLPStream );
1382 0 : free( m_optGainLPStream );
1383 0 : m_optGainLPStream = nullptr;
1384 :
1385 0 : ImageStreamIO_destroyIm( m_maxGainLPStream );
1386 0 : free( m_maxGainLPStream );
1387 0 : m_maxGainLPStream = nullptr;
1388 : }
1389 :
1390 0 : if( m_optGainStream == nullptr )
1391 : {
1392 0 : m_optGainStream = static_cast<IMAGE *>( malloc( sizeof( IMAGE ) ) );
1393 : uint32_t imsize[3];
1394 :
1395 0 : imsize[0] = m_nModes;
1396 0 : imsize[1] = 1;
1397 0 : imsize[2] = 1;
1398 0 : ImageStreamIO_createIm_gpu( m_optGainStream,
1399 : m_optGainShmimName.c_str(),
1400 : 3,
1401 : imsize,
1402 0 : psdShmimMonitorT::m_dataType,
1403 : -1,
1404 : 1,
1405 : IMAGE_NB_SEMAPHORE,
1406 : 0,
1407 : CIRCULAR_BUFFER | ZAXIS_TEMPORAL,
1408 : 0 );
1409 :
1410 0 : m_optGainStream->md->cnt0 = 0;
1411 0 : m_optGainStream->md->cnt1 = 0;
1412 :
1413 0 : m_optGainSIStream = static_cast<IMAGE *>( malloc( sizeof( IMAGE ) ) );
1414 :
1415 0 : ImageStreamIO_createIm_gpu( m_optGainSIStream,
1416 : m_optGainSIShmimName.c_str(),
1417 : 3,
1418 : imsize,
1419 0 : psdShmimMonitorT::m_dataType,
1420 : -1,
1421 : 1,
1422 : IMAGE_NB_SEMAPHORE,
1423 : 0,
1424 : CIRCULAR_BUFFER | ZAXIS_TEMPORAL,
1425 : 0 );
1426 :
1427 0 : m_optGainSIStream->md->cnt0 = 0;
1428 0 : m_optGainSIStream->md->cnt1 = 0;
1429 :
1430 0 : m_maxGainSIStream = static_cast<IMAGE *>( malloc( sizeof( IMAGE ) ) );
1431 :
1432 0 : ImageStreamIO_createIm_gpu( m_maxGainSIStream,
1433 : m_maxGainSIShmimName.c_str(),
1434 : 3,
1435 : imsize,
1436 0 : psdShmimMonitorT::m_dataType,
1437 : -1,
1438 : 1,
1439 : IMAGE_NB_SEMAPHORE,
1440 : 0,
1441 : CIRCULAR_BUFFER | ZAXIS_TEMPORAL,
1442 : 0 );
1443 :
1444 0 : m_maxGainSIStream->md->cnt0 = 0;
1445 0 : m_maxGainSIStream->md->cnt1 = 0;
1446 :
1447 0 : m_optGainLPStream = static_cast<IMAGE *>( malloc( sizeof( IMAGE ) ) );
1448 :
1449 0 : ImageStreamIO_createIm_gpu( m_optGainLPStream,
1450 : m_optGainLPShmimName.c_str(),
1451 : 3,
1452 : imsize,
1453 0 : psdShmimMonitorT::m_dataType,
1454 : -1,
1455 : 1,
1456 : IMAGE_NB_SEMAPHORE,
1457 : 0,
1458 : CIRCULAR_BUFFER | ZAXIS_TEMPORAL,
1459 : 0 );
1460 :
1461 0 : m_optGainLPStream->md->cnt0 = 0;
1462 0 : m_optGainLPStream->md->cnt1 = 0;
1463 :
1464 0 : m_maxGainLPStream = static_cast<IMAGE *>( malloc( sizeof( IMAGE ) ) );
1465 :
1466 0 : ImageStreamIO_createIm_gpu( m_maxGainLPStream,
1467 : m_maxGainLPShmimName.c_str(),
1468 : 3,
1469 : imsize,
1470 0 : psdShmimMonitorT::m_dataType,
1471 : -1,
1472 : 1,
1473 : IMAGE_NB_SEMAPHORE,
1474 : 0,
1475 : CIRCULAR_BUFFER | ZAXIS_TEMPORAL,
1476 : 0 );
1477 :
1478 0 : m_maxGainLPStream->md->cnt0 = 0;
1479 0 : m_maxGainLPStream->md->cnt1 = 0;
1480 :
1481 0 : m_modevarStream = static_cast<IMAGE *>( malloc( sizeof( IMAGE ) ) );
1482 :
1483 0 : imsize[0] = 3;
1484 0 : imsize[1] = psdShmimMonitorT::m_height;
1485 0 : imsize[2] = 1;
1486 :
1487 0 : ImageStreamIO_createIm_gpu( m_modevarStream,
1488 : m_modevarShmimName.c_str(),
1489 : 3,
1490 : imsize,
1491 0 : psdShmimMonitorT::m_dataType,
1492 : -1,
1493 : 1,
1494 : IMAGE_NB_SEMAPHORE,
1495 : 0,
1496 : CIRCULAR_BUFFER | ZAXIS_TEMPORAL,
1497 : 0 );
1498 :
1499 0 : m_modevarStream->md->cnt0 = 0;
1500 0 : m_modevarStream->md->cnt1 = 0;
1501 : }
1502 :
1503 0 : m_sinceChange = -1;
1504 :
1505 0 : m_updating = false;
1506 0 : return 0;
1507 0 : }
1508 :
1509 0 : int modalGainOpt::processImage( void *curr_src, const psdShmimT &dummy )
1510 : {
1511 : static_cast<void>( dummy );
1512 :
1513 0 : ++m_sinceChange;
1514 :
1515 0 : if( m_psdAvgTime <= 0 || m_psdTime <= 0 ) // Safety check, shouldn't happen but means we need to wait.
1516 : {
1517 0 : return 0;
1518 : }
1519 :
1520 0 : int deadTime = ( m_psdAvgTime / m_psdTime ) / m_psdOverlapFraction;
1521 :
1522 0 : if( m_sinceChange < deadTime )
1523 : {
1524 0 : return 0;
1525 : }
1526 :
1527 : // Here we would update psds, but don't do that if we're in the middle of calculating
1528 0 : std::unique_lock<std::mutex> lock( m_goptMutex, std::try_to_lock );
1529 0 : if( !lock.owns_lock() )
1530 : {
1531 : ///\todo update a frame-missed counter
1532 0 : return 0;
1533 : }
1534 :
1535 0 : m_updating = true;
1536 :
1537 0 : m_clPSDs = Eigen::Map<Eigen::Array<float, -1, -1>>(
1538 0 : static_cast<float *>( curr_src ), psdShmimMonitorT::m_width, psdShmimMonitorT::m_height );
1539 :
1540 0 : m_updating = false;
1541 :
1542 0 : lock.unlock();
1543 :
1544 0 : if( sem_post( &m_goptSemaphore ) < 0 )
1545 : {
1546 0 : return log<software_critical, -1>( { __FILE__, __LINE__, errno, 0, "Error posting to semaphore" } );
1547 : }
1548 :
1549 0 : return 0;
1550 0 : }
1551 :
1552 0 : int modalGainOpt::allocate( const freqShmimT &dummy )
1553 : {
1554 : static_cast<void>( dummy );
1555 :
1556 0 : return 0;
1557 : }
1558 :
1559 0 : int modalGainOpt::processImage( void *curr_src, const freqShmimT &dummy )
1560 : {
1561 : static_cast<void>( dummy );
1562 :
1563 0 : if( freqShmimMonitorT::m_width != 1 )
1564 : {
1565 0 : return log<software_error, -1>( { __FILE__, __LINE__, "got freq with width not 1" } );
1566 : }
1567 :
1568 0 : bool change = false;
1569 :
1570 0 : float *f = static_cast<float *>( curr_src );
1571 :
1572 0 : size_t sz = freqShmimMonitorT::m_height;
1573 :
1574 0 : if( sz != m_freq.size() )
1575 : {
1576 0 : change = true;
1577 : }
1578 :
1579 0 : if( !change ) // f is same size
1580 : {
1581 0 : for( size_t n = 0; n < sz; ++n )
1582 : {
1583 0 : if( f[n] != m_freq[n] )
1584 : {
1585 0 : change = true;
1586 0 : break;
1587 : }
1588 : }
1589 : }
1590 :
1591 0 : if( change )
1592 : {
1593 0 : m_updating = true;
1594 0 : std::lock_guard<std::mutex> lock( m_goptMutex );
1595 :
1596 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
1597 :
1598 0 : m_freq.resize( sz );
1599 :
1600 0 : for( size_t n = 0; n < sz; ++n )
1601 : {
1602 0 : m_freq[n] = f[n];
1603 : }
1604 :
1605 0 : m_fps = 2 * m_freq.back();
1606 :
1607 0 : m_sinceChange = -1;
1608 0 : m_goptUpdated = true;
1609 0 : m_freqUpdated = true;
1610 :
1611 0 : m_updating = false;
1612 0 : std::cerr << "got freq: " << sz << '\n';
1613 0 : std::cerr << " fps: " << m_fps << '\n';
1614 0 : }
1615 :
1616 0 : return 0;
1617 : }
1618 :
1619 0 : int modalGainOpt::allocate( const gainFactShmimT &dummy )
1620 : {
1621 : static_cast<void>( dummy );
1622 :
1623 0 : if( gainFactShmimMonitorT::m_height != 1 )
1624 : {
1625 0 : return log<software_error, -1>( { __FILE__, __LINE__, "got gains with height not 1" } );
1626 : }
1627 :
1628 0 : return 0;
1629 : }
1630 :
1631 0 : int modalGainOpt::processImage( void *curr_src, const gainFactShmimT &dummy )
1632 : {
1633 : static_cast<void>( dummy );
1634 :
1635 0 : bool change = false;
1636 :
1637 0 : uint32_t w = gainFactShmimMonitorT::m_width;
1638 :
1639 0 : std::unique_lock<std::mutex> lock( m_goptMutex, std::defer_lock );
1640 :
1641 0 : if( w != m_gainFacts.size() )
1642 : {
1643 0 : m_updating = true;
1644 0 : lock.lock();
1645 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
1646 :
1647 0 : change = true;
1648 0 : m_gainFacts.resize( w );
1649 : }
1650 :
1651 0 : float *g = static_cast<float *>( curr_src );
1652 :
1653 0 : for( uint32_t n = 0; n < w; ++n )
1654 : {
1655 0 : if( change || m_gainFacts[n] != g[n] )
1656 : {
1657 0 : if( !change )
1658 : {
1659 0 : m_updating = true;
1660 0 : lock.lock();
1661 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
1662 0 : change = true;
1663 : }
1664 :
1665 0 : m_gainFacts[n] = g[n];
1666 : }
1667 : }
1668 :
1669 0 : if( change )
1670 : {
1671 0 : if( m_loop )
1672 : {
1673 0 : m_sinceChange = -1;
1674 : }
1675 :
1676 0 : if(!m_pcOn)
1677 : {
1678 0 : int modesOn = 0;
1679 :
1680 0 : for(size_t n = 0; n < m_gainFacts.size(); ++n)
1681 : {
1682 0 : if(m_gainFacts[n] > 0)
1683 : {
1684 0 : ++modesOn;
1685 : }
1686 : }
1687 :
1688 0 : m_modesOn = modesOn;
1689 : }
1690 :
1691 :
1692 0 : m_updating = false;
1693 0 : std::cerr << "got gains: " << m_gainFacts.size() << "\n";
1694 :
1695 0 : lock.unlock();
1696 : }
1697 :
1698 0 : return 0;
1699 0 : }
1700 :
1701 0 : int modalGainOpt::allocate( const multFactShmimT &dummy )
1702 : {
1703 : static_cast<void>( dummy );
1704 :
1705 0 : if( multFactShmimMonitorT::m_height != 1 )
1706 : {
1707 0 : return log<software_error, -1>( { __FILE__, __LINE__, "got multcoeffs with height not 1" } );
1708 : }
1709 :
1710 0 : return 0;
1711 : }
1712 :
1713 0 : int modalGainOpt::processImage( void *curr_src, const multFactShmimT &dummy )
1714 : {
1715 : static_cast<void>( dummy );
1716 :
1717 0 : bool change = false;
1718 :
1719 0 : uint32_t w = multFactShmimMonitorT::m_width;
1720 :
1721 0 : std::unique_lock<std::mutex> lock( m_goptMutex, std::defer_lock );
1722 :
1723 0 : if( w != m_multFacts.size() )
1724 : {
1725 0 : m_updating = true;
1726 0 : lock.lock();
1727 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
1728 :
1729 0 : change = true;
1730 0 : m_multFacts.resize( w );
1731 : }
1732 :
1733 0 : float *m = static_cast<float *>( curr_src );
1734 :
1735 0 : for( uint32_t n = 0; n < w; ++n )
1736 : {
1737 0 : if( change || m_multFacts[n] != m[n] )
1738 : {
1739 0 : if( !change )
1740 : {
1741 0 : m_updating = true;
1742 0 : lock.lock();
1743 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
1744 :
1745 0 : change = true;
1746 : }
1747 :
1748 0 : m_multFacts[n] = m[n];
1749 : }
1750 : }
1751 :
1752 0 : if( change )
1753 : {
1754 0 : if( m_loop )
1755 : {
1756 0 : m_sinceChange = -1;
1757 : }
1758 :
1759 0 : m_updating = false;
1760 0 : m_goptUpdated = true;
1761 :
1762 0 : std::cerr << "got mcs: " << m_multFacts.size() << " " << w << "\n";
1763 0 : lock.unlock();
1764 : }
1765 :
1766 0 : return 0;
1767 0 : }
1768 :
1769 0 : int modalGainOpt::allocate( const pcGainFactShmimT &dummy )
1770 : {
1771 : static_cast<void>( dummy );
1772 :
1773 0 : if( pcGainFactShmimMonitorT::m_height != 1 )
1774 : {
1775 0 : return log<software_error, -1>( { __FILE__, __LINE__, "got pc gains with height not 1" } );
1776 : }
1777 :
1778 0 : return 0;
1779 : }
1780 :
1781 0 : int modalGainOpt::processImage( void *curr_src, const pcGainFactShmimT &dummy )
1782 : {
1783 : static_cast<void>( dummy );
1784 :
1785 0 : bool change = false;
1786 :
1787 0 : uint32_t w = pcGainFactShmimMonitorT::m_width;
1788 :
1789 0 : std::unique_lock<std::mutex> lock( m_goptMutex, std::defer_lock );
1790 :
1791 0 : if( w != m_pcGainFacts.size() )
1792 : {
1793 0 : m_updating = true;
1794 0 : lock.lock();
1795 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
1796 :
1797 0 : change = true;
1798 0 : m_pcGainFacts.resize( w );
1799 : }
1800 :
1801 0 : float *g = static_cast<float *>( curr_src );
1802 :
1803 0 : for( uint32_t n = 0; n < w; ++n )
1804 : {
1805 0 : if( change || m_pcGainFacts[n] != g[n] )
1806 : {
1807 0 : if( !change )
1808 : {
1809 0 : m_updating = true;
1810 0 : lock.lock();
1811 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
1812 0 : change = true;
1813 : }
1814 :
1815 0 : m_pcGainFacts[n] = g[n];
1816 : }
1817 : }
1818 :
1819 0 : if( change )
1820 : {
1821 0 : if( m_loop )
1822 : {
1823 0 : m_sinceChange = -1;
1824 : }
1825 :
1826 0 : if(m_pcOn)
1827 : {
1828 0 : int modesOn = 0;
1829 :
1830 0 : for(size_t n = 0; n < m_pcGainFacts.size(); ++n)
1831 : {
1832 0 : if(m_gainFacts[n] > 0)
1833 : {
1834 0 : ++modesOn;
1835 : }
1836 : }
1837 :
1838 0 : m_modesOn = modesOn;
1839 : }
1840 :
1841 0 : m_updating = false;
1842 0 : std::cerr << "got pc gains: " << m_pcGainFacts.size() << "\n";
1843 :
1844 0 : lock.unlock();
1845 : }
1846 :
1847 0 : return 0;
1848 0 : }
1849 :
1850 0 : int modalGainOpt::allocate( const pcMultFactShmimT &dummy )
1851 : {
1852 : static_cast<void>( dummy );
1853 :
1854 0 : if( pcMultFactShmimMonitorT::m_height != 1 )
1855 : {
1856 0 : return log<software_error, -1>( { __FILE__, __LINE__, "got pcMultcoeffs with height not 1" } );
1857 : }
1858 :
1859 0 : return 0;
1860 : }
1861 :
1862 0 : int modalGainOpt::processImage( void *curr_src, const pcMultFactShmimT &dummy )
1863 : {
1864 : static_cast<void>( dummy );
1865 :
1866 0 : bool change = false;
1867 :
1868 0 : uint32_t w = pcMultFactShmimMonitorT::m_width;
1869 :
1870 0 : std::unique_lock<std::mutex> lock( m_goptMutex, std::defer_lock );
1871 :
1872 0 : if( w != m_pcMultFacts.size() )
1873 : {
1874 0 : m_updating = true;
1875 0 : lock.lock();
1876 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
1877 :
1878 0 : change = true;
1879 0 : m_pcMultFacts.resize( w );
1880 : }
1881 :
1882 0 : float *m = static_cast<float *>( curr_src );
1883 :
1884 0 : for( uint32_t n = 0; n < w; ++n )
1885 : {
1886 0 : if( change || m_pcMultFacts[n] != m[n] )
1887 : {
1888 0 : if( !change )
1889 : {
1890 0 : m_updating = true;
1891 0 : lock.lock();
1892 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
1893 :
1894 0 : change = true;
1895 : }
1896 :
1897 0 : m_pcMultFacts[n] = m[n];
1898 : }
1899 : }
1900 :
1901 0 : if( change )
1902 : {
1903 0 : if( m_loop )
1904 : {
1905 0 : m_sinceChange = -1;
1906 : }
1907 :
1908 0 : m_updating = false;
1909 0 : m_pcgoptUpdated = true;
1910 :
1911 0 : lock.unlock();
1912 0 : std::cerr << "got mcs: " << m_multFacts.size() << "\n";
1913 : }
1914 :
1915 0 : return 0;
1916 0 : }
1917 :
1918 0 : int modalGainOpt::allocate( const numpccoeffShmimT &dummy )
1919 : {
1920 : static_cast<void>( dummy );
1921 :
1922 0 : if( numpccoeffShmimMonitorT::m_height != 2 )
1923 : {
1924 0 : return log<software_error, -1>( { __FILE__, __LINE__, "got numpccoeff's with height not 2" } );
1925 : }
1926 :
1927 0 : std::cerr << "numpccoeffShmimMonitorT::allocate\n";
1928 0 : return 0;
1929 : }
1930 :
1931 0 : int modalGainOpt::processImage( void *curr_src, const numpccoeffShmimT &dummy )
1932 : {
1933 : static_cast<void>( dummy );
1934 :
1935 0 : bool change = false;
1936 :
1937 0 : uint32_t w = numpccoeffShmimMonitorT::m_width;
1938 :
1939 0 : std::unique_lock<std::mutex> lock( m_goptMutex, std::defer_lock );
1940 :
1941 0 : if( w != m_Na.size() || w != m_Nb.size() || w != m_regCounter.size() || w != m_regScale.size() )
1942 : {
1943 0 : m_updating = true;
1944 0 : lock.lock();
1945 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
1946 :
1947 0 : change = true;
1948 0 : m_Na.resize( w );
1949 0 : m_Nb.resize( w );
1950 :
1951 0 : m_regCounter.resize( w );
1952 :
1953 : // Initialize the regCounter
1954 0 : int nc = 0;
1955 :
1956 0 : for( size_t n = 0; n < m_regCounter.size(); ++n )
1957 : {
1958 0 : m_regCounter[n] = nc;
1959 0 : ++nc;
1960 :
1961 0 : if( nc >= m_nRegCycles )
1962 : {
1963 0 : nc = 0;
1964 : }
1965 : }
1966 :
1967 0 : m_regScale.resize( w, -999 );
1968 0 : m_gmaxLP.resize( w, 0 );
1969 : }
1970 :
1971 0 : mx::improc::eigenMap<uint32_t> Npc( reinterpret_cast<uint32_t *>( curr_src ), w, 2 );
1972 :
1973 0 : for( uint32_t n = 0; n < w; ++n )
1974 : {
1975 0 : if( change || m_Na[n] != Npc( n, 0 ) || m_Nb[n] != Npc( n, 1 ) )
1976 : {
1977 0 : if( !change )
1978 : {
1979 0 : m_updating = true;
1980 0 : lock.lock();
1981 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
1982 :
1983 0 : change = true;
1984 : }
1985 :
1986 0 : m_Na[n] = Npc( n, 0 );
1987 0 : m_Nb[n] = Npc( n, 1 );
1988 : }
1989 : }
1990 :
1991 0 : if( change )
1992 : {
1993 0 : if( m_loop )
1994 : {
1995 0 : m_sinceChange = -1;
1996 : }
1997 :
1998 0 : m_updating = false;
1999 0 : m_goptUpdated = true;
2000 :
2001 0 : lock.unlock();
2002 0 : std::cerr << "got num pc coeffs: " << m_Na.size() << "\n";
2003 : }
2004 :
2005 0 : return 0;
2006 0 : }
2007 :
2008 0 : int modalGainOpt::allocate( const acoeffShmimT &dummy )
2009 : {
2010 : static_cast<void>( dummy );
2011 :
2012 0 : return 0;
2013 : }
2014 :
2015 0 : int modalGainOpt::processImage( void *curr_src, const acoeffShmimT &dummy )
2016 : {
2017 : static_cast<void>( dummy );
2018 :
2019 0 : bool change = false;
2020 :
2021 0 : std::unique_lock<std::mutex> lock( m_goptMutex, std::defer_lock );
2022 :
2023 0 : uint32_t w = acoeffShmimMonitorT::m_width;
2024 0 : uint32_t h = acoeffShmimMonitorT::m_height;
2025 :
2026 : // If there's a size change we lock
2027 0 : if( w - 1 != m_as.rows() || h != m_as.cols() || h != m_NaCurrent.size() )
2028 : {
2029 0 : m_updating = true;
2030 0 : lock.lock();
2031 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
2032 :
2033 0 : change = true;
2034 0 : m_NaCurrent.resize( h );
2035 0 : m_as.resize( w - 1, h );
2036 : }
2037 :
2038 0 : eigenMap<float> ac( reinterpret_cast<float *>( curr_src ), w, h );
2039 :
2040 0 : for( uint32_t cc = 0; cc < h; ++cc )
2041 : {
2042 0 : if( change || m_NaCurrent[cc] != ac( 0, cc ) )
2043 : {
2044 0 : if( !change )
2045 : {
2046 0 : m_updating = true;
2047 0 : lock.lock();
2048 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
2049 :
2050 0 : change = true;
2051 : }
2052 :
2053 0 : m_NaCurrent[cc] = ac( 0, cc );
2054 : }
2055 :
2056 0 : for( uint32_t rr = 1; rr < w; ++rr )
2057 : {
2058 0 : if( change || m_as( rr - 1, cc ) != ac( rr, cc ) )
2059 : {
2060 0 : if( !change )
2061 : {
2062 0 : m_updating = true;
2063 0 : lock.lock();
2064 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
2065 :
2066 0 : change = true;
2067 : }
2068 :
2069 0 : m_as( rr - 1, cc ) = ac( rr, cc );
2070 : }
2071 : }
2072 : }
2073 :
2074 0 : if( change )
2075 : {
2076 0 : if( m_loop && m_pcOn )
2077 : {
2078 0 : m_sinceChange = -1;
2079 : }
2080 :
2081 0 : m_updating = false;
2082 0 : m_pcgoptUpdated = true;
2083 :
2084 0 : lock.unlock();
2085 0 : std::cerr << "got a coeffs: " << w << ' ' << h << ' ' << m_NaCurrent.size() << "\n";
2086 : }
2087 :
2088 0 : return 0;
2089 0 : }
2090 :
2091 0 : int modalGainOpt::allocate( const bcoeffShmimT &dummy )
2092 : {
2093 : static_cast<void>( dummy );
2094 :
2095 0 : return 0;
2096 : }
2097 :
2098 0 : int modalGainOpt::processImage( void *curr_src, const bcoeffShmimT &dummy )
2099 : {
2100 : static_cast<void>( dummy );
2101 :
2102 0 : bool change = false;
2103 :
2104 0 : std::unique_lock<std::mutex> lock( m_goptMutex, std::defer_lock );
2105 :
2106 0 : uint32_t w = bcoeffShmimMonitorT::m_width;
2107 0 : uint32_t h = bcoeffShmimMonitorT::m_height;
2108 :
2109 : // If there's a size change we lock
2110 0 : if( w - 1 != m_bs.rows() || h != m_bs.cols() || h != m_NbCurrent.size() )
2111 : {
2112 0 : m_updating = true;
2113 0 : lock.lock();
2114 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
2115 :
2116 0 : change = true;
2117 :
2118 0 : m_NbCurrent.resize( h );
2119 0 : m_bs.resize( w - 1, h );
2120 : }
2121 :
2122 0 : eigenMap<float> bc( reinterpret_cast<float *>( curr_src ), w, h );
2123 :
2124 0 : for( uint32_t cc = 0; cc < h; ++cc )
2125 : {
2126 0 : if( change || m_NbCurrent[cc] != bc( 0, cc ) )
2127 : {
2128 0 : if( !change )
2129 : {
2130 0 : m_updating = true;
2131 0 : lock.lock();
2132 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
2133 :
2134 0 : change = true;
2135 : }
2136 :
2137 0 : m_NbCurrent[cc] = bc( 0, cc );
2138 : }
2139 :
2140 0 : for( uint32_t rr = 1; rr < w; ++rr )
2141 : {
2142 0 : if( change || m_bs( rr - 1, cc ) != bc( rr, cc ) )
2143 : {
2144 0 : if( !change )
2145 : {
2146 0 : m_updating = true;
2147 0 : lock.lock();
2148 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
2149 :
2150 0 : change = true;
2151 : }
2152 :
2153 0 : m_bs( rr - 1, cc ) = bc( rr, cc );
2154 : }
2155 : }
2156 : }
2157 :
2158 0 : if( change )
2159 : {
2160 0 : if( m_loop && m_pcOn )
2161 : {
2162 0 : m_sinceChange = -1;
2163 : }
2164 :
2165 0 : m_updating = false;
2166 0 : m_pcgoptUpdated = true;
2167 :
2168 0 : std::cerr << "got b coeffs: " << w << ' ' << h << ' ' << m_NbCurrent.size() << "\n";
2169 :
2170 0 : lock.unlock();
2171 : }
2172 :
2173 0 : return 0;
2174 0 : }
2175 :
2176 0 : int modalGainOpt::allocate( const gainCalShmimT &dummy )
2177 : {
2178 : static_cast<void>( dummy );
2179 :
2180 0 : return 0;
2181 : }
2182 :
2183 0 : int modalGainOpt::processImage( void *curr_src, const gainCalShmimT &dummy )
2184 : {
2185 : static_cast<void>( dummy );
2186 :
2187 0 : if( gainCalShmimMonitorT::m_height != 1 )
2188 : {
2189 0 : return log<software_error, -1>( { __FILE__, __LINE__, "got gainCals with height not 1" } );
2190 : }
2191 :
2192 0 : bool change = false;
2193 :
2194 0 : uint32_t w = gainCalShmimMonitorT::m_width;
2195 :
2196 0 : std::unique_lock<std::mutex> lock( m_goptMutex, std::defer_lock );
2197 :
2198 0 : if( w != m_gainCals.size() )
2199 : {
2200 0 : m_updating = true;
2201 0 : lock.lock();
2202 :
2203 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
2204 :
2205 0 : change = true;
2206 0 : m_gainCals.resize( w );
2207 : }
2208 :
2209 0 : float *g = static_cast<float *>( curr_src );
2210 :
2211 0 : for( uint32_t n = 0; n < w; ++n )
2212 : {
2213 0 : if( change || m_gainCals[n] != g[n] )
2214 : {
2215 0 : if( !change )
2216 : {
2217 0 : m_updating = true;
2218 0 : lock.lock();
2219 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
2220 :
2221 0 : change = true;
2222 : }
2223 :
2224 0 : m_gainCals[n] = g[n];
2225 : }
2226 : }
2227 :
2228 0 : if( change )
2229 : {
2230 0 : m_sinceChange = -1;
2231 0 : m_updating = false;
2232 0 : std::cerr << "got gainCals: " << m_gainCals.size() << "\n";
2233 0 : lock.unlock();
2234 : }
2235 :
2236 0 : return 0;
2237 0 : }
2238 :
2239 0 : int modalGainOpt::allocate( const gainCalFactShmimT &dummy )
2240 : {
2241 : static_cast<void>( dummy );
2242 :
2243 0 : return 0;
2244 : }
2245 :
2246 0 : int modalGainOpt::processImage( void *curr_src, const gainCalFactShmimT &dummy )
2247 : {
2248 : static_cast<void>( dummy );
2249 :
2250 0 : if( gainCalFactShmimMonitorT::m_height != 1 )
2251 : {
2252 0 : return log<software_error, -1>( { __FILE__, __LINE__, "got gainCalFacts with height not 1" } );
2253 : }
2254 :
2255 0 : bool change = false;
2256 :
2257 0 : uint32_t w = gainCalFactShmimMonitorT::m_width;
2258 :
2259 0 : std::unique_lock<std::mutex> lock( m_goptMutex, std::defer_lock );
2260 :
2261 0 : if( w != m_gainCalFacts.size() )
2262 : {
2263 0 : m_updating = true;
2264 0 : lock.lock();
2265 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
2266 :
2267 0 : change = true;
2268 0 : m_gainCalFacts.resize( w );
2269 : }
2270 :
2271 0 : float *g = static_cast<float *>( curr_src );
2272 :
2273 0 : for( uint32_t n = 0; n < w; ++n )
2274 : {
2275 0 : if( change || m_gainCalFacts[n] != g[n] )
2276 : {
2277 0 : if( !change )
2278 : {
2279 0 : m_updating = true;
2280 0 : lock.lock();
2281 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
2282 :
2283 0 : change = true;
2284 : }
2285 :
2286 0 : m_gainCalFacts[n] = g[n];
2287 : }
2288 : }
2289 :
2290 0 : if( change )
2291 : {
2292 0 : m_sinceChange = -1;
2293 0 : m_updating = false;
2294 0 : std::cerr << "got gainCalsFacts: " << m_gainCalFacts.size() << "\n";
2295 0 : lock.unlock();
2296 : }
2297 :
2298 0 : return 0;
2299 0 : }
2300 :
2301 0 : int modalGainOpt::allocate( const tauShmimT &dummy )
2302 : {
2303 : static_cast<void>( dummy );
2304 :
2305 0 : return 0;
2306 : }
2307 :
2308 0 : int modalGainOpt::processImage( void *curr_src, const tauShmimT &dummy )
2309 : {
2310 : static_cast<void>( dummy );
2311 :
2312 0 : if( tauShmimMonitorT::m_height != 1 )
2313 : {
2314 0 : return log<software_error, -1>( { __FILE__, __LINE__, "got tau with height not 1" } );
2315 : }
2316 :
2317 0 : bool change = false;
2318 :
2319 0 : uint32_t w = tauShmimMonitorT::m_width;
2320 :
2321 0 : std::unique_lock<std::mutex> lock( m_goptMutex, std::defer_lock );
2322 :
2323 0 : if( w != m_taus.size() )
2324 : {
2325 0 : m_updating = true;
2326 0 : lock.lock();
2327 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
2328 :
2329 0 : change = true;
2330 0 : m_taus.resize( w );
2331 : }
2332 :
2333 0 : float *t = static_cast<float *>( curr_src );
2334 :
2335 0 : for( uint32_t n = 0; n < w; ++n )
2336 : {
2337 0 : if( change || m_taus[n] != t[n] )
2338 : {
2339 0 : if( !change )
2340 : {
2341 0 : m_updating = true;
2342 0 : lock.lock();
2343 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
2344 :
2345 0 : change = true;
2346 : }
2347 :
2348 0 : m_taus[n] = t[n];
2349 : }
2350 : }
2351 :
2352 0 : if( change )
2353 : {
2354 0 : m_sinceChange = -1;
2355 0 : m_updating = false;
2356 0 : m_goptUpdated = true;
2357 0 : std::cerr << "got taus: " << m_taus.size() << "\n";
2358 0 : lock.unlock();
2359 : }
2360 0 : return 0;
2361 0 : }
2362 :
2363 0 : int modalGainOpt::allocate( const noiseShmimT &dummy )
2364 : {
2365 : static_cast<void>( dummy );
2366 :
2367 0 : return 0;
2368 : }
2369 :
2370 0 : int modalGainOpt::processImage( void *curr_src, const noiseShmimT &dummy )
2371 : {
2372 : static_cast<void>( dummy );
2373 :
2374 0 : if( noiseShmimMonitorT::m_width != 3 )
2375 : {
2376 0 : return log<software_error, -1>( { __FILE__, __LINE__, "got tau with width not 3" } );
2377 : }
2378 :
2379 0 : bool change = false;
2380 :
2381 0 : uint32_t h = noiseShmimMonitorT::m_height;
2382 :
2383 0 : std::unique_lock<std::mutex> lock( m_goptMutex, std::defer_lock );
2384 :
2385 0 : if( h != m_noiseParams.cols() )
2386 : {
2387 0 : m_updating = true;
2388 0 : lock.lock();
2389 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
2390 :
2391 0 : change = true;
2392 0 : m_noiseParams.resize( 3, h );
2393 : }
2394 :
2395 0 : mx::improc::eigenMap<float> np( static_cast<float *>( curr_src ), 3, h );
2396 :
2397 0 : for( uint32_t n = 0; n < h; ++n )
2398 : {
2399 0 : if( change || m_noiseParams( 0, n ) != np( 0, n ) || m_noiseParams( 1, n ) != np( 1, n ) ||
2400 0 : m_noiseParams( 2, n ) != np( 2, n ) )
2401 : {
2402 0 : if( !change )
2403 : {
2404 0 : m_updating = true;
2405 0 : lock.lock();
2406 0 : m_updating = true; // Make sure it didn't get set to false by thread that had the lock
2407 :
2408 0 : change = true;
2409 : }
2410 :
2411 0 : m_noiseParams.col( n ) = np.col( n );
2412 : }
2413 : }
2414 :
2415 0 : if( change )
2416 : {
2417 0 : m_sinceChange = -1;
2418 0 : m_updating = false;
2419 0 : m_goptUpdated = true;
2420 0 : std::cerr << "got noise params: " << m_noiseParams.rows() << " x " << m_noiseParams.cols() << "\n";
2421 0 : lock.unlock();
2422 : }
2423 0 : return 0;
2424 0 : }
2425 :
2426 0 : int modalGainOpt::allocate( const wfsavgShmimT &dummy )
2427 : {
2428 : static_cast<void>( dummy );
2429 :
2430 0 : std::cerr << "Got WFS avg: " << wfsavgShmimMonitorT::m_width << " x " << wfsavgShmimMonitorT::m_height << '\n';
2431 0 : return 0;
2432 : }
2433 :
2434 0 : int modalGainOpt::processImage( void *curr_src, const wfsavgShmimT &dummy )
2435 : {
2436 : static_cast<void>( dummy );
2437 :
2438 0 : m_wfsavg = mx::improc::eigenMap<float>(
2439 0 : reinterpret_cast<float *>( curr_src ), wfsavgShmimMonitorT::m_width, wfsavgShmimMonitorT::m_height );
2440 :
2441 0 : if( m_wfsavg.rows() == m_wfsmask.rows() && m_wfsavg.cols() == m_wfsmask.cols() )
2442 : {
2443 0 : m_counts = ( m_wfsavg * m_wfsmask ).sum();
2444 :
2445 : // std::cerr << "counts: " << m_counts << '\n';
2446 : }
2447 :
2448 0 : return 0;
2449 : }
2450 :
2451 0 : int modalGainOpt::allocate( const wfsmaskShmimT &dummy )
2452 : {
2453 : static_cast<void>( dummy );
2454 :
2455 0 : std::cerr << "Got WFS mask: " << wfsmaskShmimMonitorT::m_width << " x " << wfsmaskShmimMonitorT::m_height << '\n';
2456 0 : return 0;
2457 : }
2458 :
2459 0 : int modalGainOpt::processImage( void *curr_src, const wfsmaskShmimT &dummy )
2460 : {
2461 : static_cast<void>( dummy );
2462 :
2463 0 : m_wfsmask = mx::improc::eigenMap<float>(
2464 0 : reinterpret_cast<float *>( curr_src ), wfsmaskShmimMonitorT::m_width, wfsmaskShmimMonitorT::m_height );
2465 :
2466 0 : m_npix = m_wfsmask.sum();
2467 :
2468 0 : if( m_wfsavg.rows() == m_wfsmask.rows() && m_wfsavg.cols() == m_wfsmask.cols() )
2469 : {
2470 0 : m_counts = ( m_wfsavg * m_wfsmask ).sum();
2471 : }
2472 :
2473 0 : return 0;
2474 : }
2475 :
2476 0 : int modalGainOpt::checkSizes()
2477 : {
2478 0 : static std::vector<bool> logged( 50, false );
2479 :
2480 0 : int L = 0;
2481 0 : if( m_clPSDs.rows() == 0 || m_clPSDs.cols() == 0 ) // somehow here without any data
2482 : {
2483 0 : if( !logged[L] )
2484 : {
2485 0 : log<software_error>( { __FILE__, __LINE__, "PSDs have not been updated" } );
2486 : }
2487 0 : logged[L] = true;
2488 0 : return -1;
2489 : }
2490 0 : logged[L++] = false;
2491 :
2492 0 : if( static_cast<size_t>( m_clPSDs.rows() ) != m_freq.size() )
2493 : {
2494 0 : if( !logged[L] )
2495 : {
2496 0 : log<software_error>( { __FILE__, __LINE__, "PSDs and freq size mismatch" } );
2497 : }
2498 0 : logged[L] = true;
2499 0 : return -1;
2500 : }
2501 0 : logged[L++] = false;
2502 :
2503 0 : if( m_nModes != m_gainFacts.size() )
2504 : {
2505 0 : if( !logged[L] )
2506 : {
2507 0 : log<software_error>( { __FILE__, __LINE__, "PSDs and gains number of modes mismatch" } );
2508 : }
2509 0 : logged[L] = true;
2510 0 : return -1;
2511 : }
2512 0 : logged[L++] = false;
2513 :
2514 0 : if( m_nModes != m_multFacts.size() )
2515 : {
2516 0 : if( !logged[L] )
2517 : {
2518 0 : log<software_error>( { __FILE__, __LINE__, "PSDs and mult coeffs number of modes mismatch" } );
2519 : }
2520 0 : logged[L] = true;
2521 0 : return -1;
2522 : }
2523 0 : logged[L++] = false;
2524 :
2525 0 : if( m_nModes != m_gainCals.size() )
2526 : {
2527 0 : if( !logged[L] )
2528 : {
2529 0 : log<software_error>( { __FILE__, __LINE__, "PSDs and gain cals number of modes mismatch" } );
2530 : }
2531 0 : logged[L] = true;
2532 0 : return -1;
2533 : }
2534 0 : logged[L++] = false;
2535 :
2536 0 : if( m_nModes != m_gainCalFacts.size() )
2537 : {
2538 0 : if( !logged[L] )
2539 : {
2540 0 : log<software_error>( { __FILE__, __LINE__, "PSDs and gain cal facts number of modes mismatch" } );
2541 : }
2542 0 : logged[L] = true;
2543 0 : return -1;
2544 : }
2545 0 : logged[L++] = false;
2546 :
2547 0 : if( m_nModes != m_taus.size() )
2548 : {
2549 0 : if( !logged[L] )
2550 : {
2551 0 : log<software_error>( { __FILE__, __LINE__, "Loop taus have not been set" } );
2552 : }
2553 0 : logged[L] = true;
2554 0 : return -1;
2555 : }
2556 0 : logged[L++] = false;
2557 :
2558 : /*if( m_clPSDs.cols() != m_noiseParams.cols() || m_noiseParams.rows() != 3 )
2559 : {
2560 : if( !logged[L] )
2561 : {
2562 : log<software_error>( { __FILE__, __LINE__, "noise params have not been set" } );
2563 : }
2564 : logged[L] = true;
2565 : return -1;
2566 : }
2567 : logged[L++] = false;*/
2568 :
2569 0 : if( m_fps <= 0 )
2570 : {
2571 0 : if( !logged[L] )
2572 : {
2573 0 : log<software_error>( { __FILE__, __LINE__, "Loop fps has not been set" } );
2574 : }
2575 0 : logged[L] = true;
2576 0 : return -1;
2577 : }
2578 0 : logged[L++] = false;
2579 :
2580 0 : if( m_olPSDStream == nullptr )
2581 : {
2582 0 : if( !logged[L] )
2583 : {
2584 0 : log<software_error>( { __FILE__, __LINE__, "m_olPSDStream is not allocated" } );
2585 : }
2586 0 : logged[L] = true;
2587 0 : return -1;
2588 : }
2589 0 : logged[L++] = false;
2590 :
2591 0 : if( m_noisePSDStream == nullptr )
2592 : {
2593 0 : if( !logged[L] )
2594 : {
2595 0 : log<software_error>( { __FILE__, __LINE__, "m_noisePSDStream is not allocated" } );
2596 : }
2597 0 : logged[L] = true;
2598 0 : return -1;
2599 : }
2600 0 : logged[L++] = false;
2601 :
2602 0 : if( m_clXferCurrentStream == nullptr )
2603 : {
2604 0 : if( !logged[L] )
2605 : {
2606 0 : log<software_error>( { __FILE__, __LINE__, "m_clXferCurrentStream is not allocated" } );
2607 : }
2608 0 : logged[L] = true;
2609 0 : return -1;
2610 : }
2611 0 : logged[L++] = false;
2612 :
2613 0 : if( m_clXferSIStream == nullptr )
2614 : {
2615 0 : if( !logged[L] )
2616 : {
2617 0 : log<software_error>( { __FILE__, __LINE__, "m_clXferSIStream is not allocated" } );
2618 : }
2619 0 : logged[L] = true;
2620 0 : return -1;
2621 : }
2622 0 : logged[L++] = false;
2623 :
2624 0 : if( m_optGainStream == nullptr )
2625 : {
2626 0 : if( !logged[L] )
2627 : {
2628 0 : log<software_error>( { __FILE__, __LINE__, "optGainsStream is not allocated" } );
2629 : }
2630 0 : logged[L] = true;
2631 0 : return -1;
2632 : }
2633 0 : logged[L++] = false;
2634 :
2635 0 : if( m_optGainSIStream == nullptr )
2636 : {
2637 0 : if( !logged[L] )
2638 : {
2639 0 : log<software_error>( { __FILE__, __LINE__, "optGainsStream SI is not allocated" } );
2640 : }
2641 0 : logged[L] = true;
2642 0 : return -1;
2643 : }
2644 0 : logged[L++] = false;
2645 :
2646 : // Check the PC shmims that we don't automatically create
2647 0 : if( m_Na.size() != m_nModes || m_NaCurrent.size() != m_nModes || (size_t)m_as.cols() != m_nModes ||
2648 0 : m_Nb.size() != m_nModes || m_NbCurrent.size() != m_nModes || (size_t)m_bs.cols() != m_nModes ||
2649 0 : m_pcGainFacts.size() != m_nModes || m_pcMultFacts.size() != m_nModes )
2650 : {
2651 :
2652 0 : if( allocatePCShmims() < 0 )
2653 : {
2654 0 : log<software_error>( { __FILE__, __LINE__, "error allocating PC shmims" } );
2655 : }
2656 :
2657 0 : if( m_Na.size() != m_nModes || m_NaCurrent.size() != m_nModes || (size_t)m_as.cols() != m_nModes ||
2658 0 : m_Nb.size() != m_nModes || m_NbCurrent.size() != m_nModes || (size_t)m_bs.cols() != m_nModes ||
2659 0 : m_pcGainFacts.size() != m_nModes || m_pcMultFacts.size() != m_nModes )
2660 : {
2661 :
2662 0 : if( !logged[L] )
2663 : {
2664 0 : log<software_error>( { __FILE__, __LINE__, "PC shmims not allcoated" } );
2665 : }
2666 0 : logged[L] = true;
2667 0 : return -1;
2668 : }
2669 : else
2670 : {
2671 0 : logged[L] = false;
2672 : }
2673 : }
2674 : else
2675 : {
2676 0 : logged[L] = false;
2677 : }
2678 0 : ++L;
2679 :
2680 0 : if( m_clXferLPStream == nullptr )
2681 : {
2682 0 : if( !logged[L] )
2683 : {
2684 0 : log<software_error>( { __FILE__, __LINE__, "m_clXferLPStream is not allocated" } );
2685 : }
2686 0 : logged[L] = true;
2687 0 : return -1;
2688 : }
2689 0 : logged[L++] = false;
2690 :
2691 0 : if( m_optGainLPStream == nullptr )
2692 : {
2693 0 : if( !logged[L] )
2694 : {
2695 0 : log<software_error>( { __FILE__, __LINE__, "m_optGainLPStream is not allocated" } );
2696 : }
2697 0 : logged[L] = true;
2698 0 : return -1;
2699 : }
2700 0 : logged[L++] = false;
2701 :
2702 0 : if( m_nModes != m_optGainLP.size() )
2703 : {
2704 0 : if( !logged[L] )
2705 : {
2706 0 : log<software_error>( { __FILE__, __LINE__, "m_optGainLP is not allocated" } );
2707 : }
2708 0 : logged[L] = true;
2709 0 : return -1;
2710 : }
2711 0 : logged[L++] = false;
2712 :
2713 0 : return 0;
2714 : }
2715 :
2716 0 : float modalGainOpt::noisePSD( int n )
2717 : {
2718 0 : float mc = m_noiseParams( 1, n ) * m_counts / m_emg;
2719 :
2720 0 : float snr2 = ( mc * mc ) / ( mc + m_npix * pow( m_noiseParams( 2, n ) / m_emg, 2 ) );
2721 :
2722 0 : return 0.05 * m_noiseParams( 0, n ) / snr2;
2723 : }
2724 :
2725 0 : void modalGainOpt::goptThreadStart( modalGainOpt *p )
2726 : {
2727 0 : p->goptThreadExec();
2728 0 : }
2729 :
2730 0 : void modalGainOpt::goptThreadExec()
2731 : {
2732 0 : m_goptThreadID = syscall( SYS_gettid );
2733 :
2734 0 : while( m_goptThreadInit == true && shutdown() == 0 )
2735 : {
2736 0 : sleep( 1 );
2737 : }
2738 :
2739 0 : while( shutdown() == 0 )
2740 : {
2741 : timespec ts;
2742 0 : XWC_SEM_WAIT_TS_RETVOID( ts, 1, 0 );
2743 :
2744 0 : if( sem_timedwait( &m_goptSemaphore, &ts ) == 0 )
2745 : {
2746 0 : std::lock_guard<std::mutex> lock( m_goptMutex );
2747 :
2748 0 : if( checkSizes() < 0 )
2749 : {
2750 0 : std::cerr << "check sizes failed\n";
2751 0 : continue; // we just wait
2752 : }
2753 :
2754 : // m_doPCCalcs = false;
2755 :
2756 0 : if( m_goptUpdated || m_pcgoptUpdated || m_freqUpdated || m_goptCurrent.size() != m_gainFacts.size() )
2757 : {
2758 0 : if( m_goptCurrent.size() != m_gainFacts.size() )
2759 : {
2760 0 : m_freqUpdated = true; // force freq update in this case
2761 : }
2762 :
2763 0 : std::cerr << "updating gopt structures\n";
2764 :
2765 0 : m_goptCurrent.resize( m_gainFacts.size() );
2766 0 : m_goptSI.resize( m_gainFacts.size() );
2767 0 : m_goptLP.resize( m_gainFacts.size() );
2768 0 : m_linPred.resize( m_gainFacts.size() );
2769 :
2770 0 : for( size_t n = 0; n < m_goptCurrent.size(); ++n )
2771 : {
2772 0 : m_goptCurrent[n].Ti( 1.0 / m_fps );
2773 0 : m_goptCurrent[n].tau( m_taus[n] );
2774 :
2775 0 : m_goptSI[n].Ti( 1.0 / m_fps );
2776 0 : m_goptSI[n].tau( m_taus[n] );
2777 :
2778 0 : m_goptLP[n].Ti( 1.0 / m_fps );
2779 0 : m_goptLP[n].tau( m_taus[n] );
2780 :
2781 0 : if( !m_pcOn )
2782 : {
2783 0 : m_goptCurrent[n].setLeakyIntegrator( m_mult * m_multFacts[n] );
2784 : }
2785 : else
2786 : {
2787 0 : std::vector<float> ta( m_NaCurrent[n] );
2788 0 : for( size_t m = 0; m < ta.size(); ++m )
2789 : {
2790 0 : ta[m] = m_as( m, n );
2791 : }
2792 0 : m_goptCurrent[n].a( ta );
2793 :
2794 0 : std::vector<float> tb( m_NbCurrent[n] );
2795 0 : for( size_t m = 0; m < tb.size(); ++m )
2796 : {
2797 0 : tb[m] = m_bs( m, n );
2798 : }
2799 0 : m_goptCurrent[n].b( tb );
2800 :
2801 0 : m_goptCurrent[n].remember( m_pcMult * m_pcMultFacts[n] );
2802 0 : }
2803 :
2804 0 : m_goptSI[n].setLeakyIntegrator( m_mult * m_multFacts[n] );
2805 :
2806 0 : if( m_freqUpdated )
2807 : {
2808 0 : m_goptCurrent[n].f( m_freq );
2809 0 : m_goptSI[n].f( m_freq );
2810 0 : m_goptLP[n].f( m_freq );
2811 : }
2812 :
2813 0 : m_gmaxSI[n] = m_goptSI[n].maxStableGain();
2814 : }
2815 :
2816 0 : m_goptUpdated = false;
2817 0 : m_pcgoptUpdated = false;
2818 0 : m_freqUpdated = false;
2819 :
2820 0 : std::cerr << "done.\n";
2821 : }
2822 :
2823 : MGO_BREADCRUMB;
2824 0 : if( m_updating )
2825 : {
2826 0 : continue;
2827 : }
2828 :
2829 0 : timePointT t0 = std::chrono::steady_clock::now();
2830 :
2831 : MGO_BREADCRUMB;
2832 :
2833 0 : int off = 0;
2834 0 : int offLP = 0;
2835 :
2836 0 : #pragma omp parallel for num_threads( 15 )
2837 : for( size_t n = 0; n < m_goptCurrent.size(); ++n )
2838 : {
2839 : if( m_updating || m_shutdown )
2840 : {
2841 : continue; // don't break b/c of omp
2842 : }
2843 :
2844 : if( !m_pcOn )
2845 : {
2846 : MGO_BREADCRUMB;
2847 :
2848 : for( size_t f = 0; f < m_goptCurrent[n].f_size(); ++f )
2849 : {
2850 : m_clXferCurrent( f, n ) =
2851 : m_goptCurrent[n].clETF2( f, m_gain * m_gainFacts[n] * m_gainCals[n] * m_opticalGain );
2852 : }
2853 : }
2854 : else
2855 : {
2856 : for( size_t f = 0; f < m_goptCurrent[n].f_size(); ++f )
2857 : {
2858 : m_clXferCurrent( f, n ) =
2859 : m_goptCurrent[n].clETF2( f, m_pcGain * m_pcGainFacts[n] * m_gainCals[n] * m_opticalGain );
2860 : }
2861 : }
2862 :
2863 : MGO_BREADCRUMB;
2864 : // Calculate the OL PSD with the current gopt (PC or SI)
2865 : float og2 = m_opticalGain * m_opticalGain;
2866 : if( !m_loop )
2867 : {
2868 : MGO_BREADCRUMB;
2869 : for( size_t f = 1; f < m_goptCurrent[n].f_size(); ++f )
2870 : {
2871 : m_olPSDs[n][f] = m_clPSDs( f, n ) / og2;
2872 : }
2873 : }
2874 : else
2875 : {
2876 : MGO_BREADCRUMB;
2877 : for( size_t f = 1; f < m_goptCurrent[n].f_size(); ++f )
2878 : {
2879 : m_olPSDs[n][f] = ( m_clPSDs( f, n ) / og2 ) / m_clXferCurrent( f, n );
2880 : }
2881 : }
2882 :
2883 : MGO_BREADCRUMB;
2884 :
2885 : m_olPSDs[n][0] = m_olPSDs[n][1];
2886 :
2887 : bool flagOff = false;
2888 : float extrap = 0;
2889 :
2890 : // Calculate the noise as the 25th percentile in log10
2891 : // this is to avoid spikes that make the noise too high
2892 : size_t f0 = 0.5 * m_goptCurrent[n].f_size();
2893 : size_t f1 = m_goptCurrent[n].f_size();
2894 :
2895 : std::vector<float> npsd( f1 - f0 );
2896 : for( size_t f = f0; f < f1; ++f )
2897 : {
2898 : npsd[f - f0] = log10( m_olPSDs[n][f] );
2899 : }
2900 : float pct = 0.25;
2901 :
2902 : MGO_BREADCRUMB;
2903 : if( n < 2 )
2904 : {
2905 : pct = 0.05;
2906 : }
2907 :
2908 : auto nth = npsd.begin() + pct * ( f1 - f0 );
2909 : std::nth_element( npsd.begin(), nth, npsd.end() );
2910 :
2911 : MGO_BREADCRUMB;
2912 :
2913 : float noise = pow( 10, *nth );
2914 : for( size_t f = 0; f < m_goptCurrent[n].f_size(); ++f )
2915 : {
2916 : m_nPSDs[n][f] = noise;
2917 : }
2918 :
2919 : if( m_extrapOL )
2920 : {
2921 : for( size_t f = 0; f < m_goptCurrent[n].f_size(); ++f )
2922 : {
2923 : m_olPSDs[n][f] = m_olPSDs[n][f] - m_nPSDs[n][f];
2924 : }
2925 :
2926 : MGO_BREADCRUMB;
2927 :
2928 : // Calculate an average extrapolation point referenced to 1 Hz
2929 :
2930 : extrap = 0;
2931 : int nexp = 0;
2932 : int noff = 0;
2933 : for( size_t f = 1; f < 0.05 * m_freq.size(); ++f )
2934 : {
2935 : // This is a threshold for "too noisy"
2936 : ///\todo make configurable
2937 : if( m_olPSDs[n][f] <= 0.1 * m_nPSDs[n][f] )
2938 : {
2939 : ++noff;
2940 : continue;
2941 : }
2942 : extrap += log10( m_olPSDs[n][f] * pow( m_freq[f] / m_freq[1], 8. / 3. ) );
2943 : ++nexp;
2944 : }
2945 :
2946 : extrap = pow( 10, extrap / nexp );
2947 :
2948 : MGO_BREADCRUMB;
2949 : if( noff > 0.5 * ( 0.05 * m_freq.size() - 1 ) && n > 1 )
2950 : {
2951 : flagOff = true;
2952 : }
2953 : }
2954 :
2955 : // flagOff = false;
2956 :
2957 : MGO_BREADCRUMB;
2958 :
2959 : if( flagOff )
2960 : {
2961 : MGO_BREADCRUMB;
2962 : #pragma omp critical
2963 : {
2964 : ++off;
2965 : }
2966 :
2967 : for( size_t f = 0; f < m_goptCurrent[n].f_size(); ++f )
2968 : {
2969 : m_olPSDs[n][f] = m_nPSDs[n][f];
2970 : }
2971 :
2972 : m_modeVarOL[n] = mx::sigproc::psdVar( m_freq, m_olPSDs[n] );
2973 :
2974 : m_optGainSI[n] = 0;
2975 : m_modeVarSI[n] = m_modeVarOL[n];
2976 :
2977 : for( size_t f = 0; f < m_goptCurrent[n].f_size(); ++f )
2978 : {
2979 : m_clXferSI( f, n ) = 1;
2980 : }
2981 :
2982 : m_timesOnSI[n] = 0;
2983 : }
2984 : else
2985 : {
2986 : MGO_BREADCRUMB;
2987 :
2988 : if( m_extrapOL )
2989 : {
2990 : std::vector<float> tosmooth( m_nFreq );
2991 :
2992 : for( size_t f = 0; f < m_nFreq; ++f )
2993 : {
2994 : if( m_olPSDs[n][f] < 0 )
2995 : {
2996 : tosmooth[f] = extrap * pow( m_freq[1] / m_freq[f], 8. / 3. );
2997 : }
2998 : else
2999 : {
3000 : tosmooth[f] = m_olPSDs[n][f];
3001 : }
3002 : }
3003 :
3004 : std::vector<float> l10( m_nFreq ), smol( m_nFreq );
3005 : std::vector<int> smw( m_nFreq );
3006 : smw[0] = 2;
3007 : smw[1] = 2;
3008 : l10[0] = log10( tosmooth[0] );
3009 : l10[1] = log10( tosmooth[1] );
3010 :
3011 : for( size_t f = 2; f < smw.size(); ++f )
3012 : {
3013 : smw[f] = 2 + static_cast<float>( f ) / 10;
3014 : l10[f] = log10( tosmooth[f] );
3015 : }
3016 :
3017 : mx::math::vectorSmoothMean( smol, l10, smw );
3018 :
3019 : for( size_t f = 0; f < m_nFreq; ++f )
3020 : {
3021 : smol[f] = pow( 10, smol[f] );
3022 : }
3023 :
3024 : for( size_t f = 0; f < m_nFreq; ++f )
3025 : {
3026 : if( m_olPSDs[n][f] < m_nPSDs[n][f] )
3027 : {
3028 : m_olPSDs[n][f] = smol[f];
3029 : }
3030 : }
3031 : }
3032 :
3033 : MGO_BREADCRUMB;
3034 : m_modeVarOL[n] = mx::sigproc::psdVar( m_freq, m_olPSDs[n] );
3035 :
3036 : m_optGainSI[n] =
3037 : m_goptSI[n].optGainOpenLoop( m_modeVarSI[n], m_olPSDs[n], m_nPSDs[n], m_gmaxSI[n], false );
3038 :
3039 : if( ( m_modeVarSI[n] - m_modeVarOL[n] ) / m_modeVarOL[n] > -0.001 )
3040 : {
3041 : #pragma omp critical
3042 : {
3043 : ++off;
3044 : }
3045 :
3046 : MGO_BREADCRUMB;
3047 : m_optGainSI[n] = 0;
3048 : m_modeVarSI[n] = m_modeVarOL[n];
3049 :
3050 : for( size_t f = 0; f < m_goptCurrent[n].f_size(); ++f )
3051 : {
3052 : m_clXferSI( f, n ) = 1;
3053 : }
3054 :
3055 : m_timesOnSI[n] = 0;
3056 : }
3057 : else if( m_timesOnSI[n] < 5 )
3058 : {
3059 : #pragma omp critical
3060 : {
3061 : ++off;
3062 : }
3063 :
3064 : MGO_BREADCRUMB;
3065 : // Would be on, but we debounce
3066 : m_optGainSI[n] = 0;
3067 : m_modeVarSI[n] = m_modeVarOL[n];
3068 :
3069 : for( size_t f = 0; f < m_goptCurrent[n].f_size(); ++f )
3070 : {
3071 : m_clXferSI( f, n ) = 1;
3072 : }
3073 :
3074 : ++m_timesOnSI[n];
3075 : }
3076 : else
3077 : {
3078 : MGO_BREADCRUMB;
3079 : for( size_t f = 0; f < m_goptCurrent[n].f_size(); ++f )
3080 : {
3081 : m_clXferSI( f, n ) = m_goptSI[n].clETF2( f, m_optGainSI[n] );
3082 : }
3083 :
3084 : ++m_timesOnSI[n];
3085 : }
3086 : }
3087 :
3088 : if( m_doPCCalcs && !flagOff )
3089 : {
3090 : MGO_BREADCRUMB;
3091 : if( m_regScale[n] == -999 || m_regCounter[n] >= m_nRegCycles )
3092 : {
3093 : MGO_BREADCRUMB;
3094 : float min_sc;
3095 : float gmax_lp = 0;
3096 :
3097 : if( m_linPred[n].regularizeCoefficients( gmax_lp,
3098 : m_optGainLP[n],
3099 : m_modeVarLP[n],
3100 : min_sc,
3101 : m_goptLP[n],
3102 : m_olPSDs[n],
3103 : m_nPSDs[n],
3104 : m_Na[n] ) < 0 )
3105 : {
3106 : MGO_BREADCRUMB;
3107 :
3108 : m_optGainLP[n] = 0;
3109 : m_modeVarLP[n] = m_modeVarOL[n];
3110 :
3111 : ///\todo what to do about coeffs?
3112 : }
3113 :
3114 : MGO_BREADCRUMB;
3115 :
3116 : if( m_regScale[n] == -999 )
3117 : {
3118 : MGO_BREADCRUMB;
3119 : m_regCounter[n] = n % m_nRegCycles;
3120 : }
3121 : else
3122 : {
3123 : MGO_BREADCRUMB;
3124 : m_regCounter[n] = 0;
3125 : }
3126 :
3127 : m_regScale[n] = min_sc;
3128 : m_gmaxLP[n] = gmax_lp;
3129 : }
3130 : else
3131 : {
3132 : MGO_BREADCRUMB;
3133 : // use pre-regularized version
3134 : float psdReg = m_olPSDs[n][0];
3135 : if( m_linPred[n].calcCoefficients(
3136 : m_olPSDs[n], m_nPSDs[n], psdReg * pow( 10, -m_regScale[n] / 10 ), m_Na[n] ) < 0 )
3137 : {
3138 : m_optGainLP[n] = 0;
3139 : m_modeVarLP[n] = m_modeVarOL[n];
3140 :
3141 : ///\todo what to do about coeffs?
3142 : }
3143 : else
3144 : {
3145 : m_goptLP[n].a( m_linPred[n].m_lp.m_c );
3146 : m_goptLP[n].b( m_linPred[n].m_lp.m_c );
3147 :
3148 : m_optGainLP[n] = m_goptLP[n].optGainOpenLoop(
3149 : m_modeVarLP[n], m_olPSDs[n], m_nPSDs[n], m_gmaxLP[n], false );
3150 : }
3151 : ++m_regCounter[n];
3152 : }
3153 :
3154 : MGO_BREADCRUMB;
3155 :
3156 : /*if( ( m_modeVarLP[n] - m_modeVarOL[n] ) / m_modeVarOL[n] > -0.001 )
3157 : {
3158 : m_optGainLP[n] = 0;
3159 : m_modeVarLP[n] = m_modeVarOL[n];
3160 :
3161 : for( size_t f = 0; f < m_goptCurrent[n].f_size(); ++f )
3162 : {
3163 : m_clXferLP( f, n ) = 1;
3164 : }
3165 :
3166 : m_timesOnLP[n] = 0;
3167 : }
3168 : else*/
3169 : if( ( m_modeVarLP[n] - m_modeVarSI[n] ) / m_modeVarSI[n] > -0.001 )
3170 : {
3171 : #pragma omp critical
3172 : {
3173 : ++offLP;
3174 : }
3175 :
3176 :
3177 : MGO_BREADCRUMB;
3178 : m_optGainLP[n] = m_optGainSI[n];
3179 : m_modeVarLP[n] = m_modeVarSI[n];
3180 :
3181 : for( size_t f = 0; f < m_goptCurrent[n].f_size(); ++f )
3182 : {
3183 : m_clXferLP( f, n ) = m_clXferSI( f, n );
3184 : }
3185 :
3186 : m_timesOnLP[n] = 0;
3187 : }
3188 : else if( m_timesOnLP[n] < 5 )
3189 : {
3190 : #pragma omp critical
3191 : {
3192 : ++offLP;
3193 : }
3194 :
3195 :
3196 : MGO_BREADCRUMB;
3197 : m_optGainLP[n] = m_optGainSI[n];
3198 : m_modeVarLP[n] = m_modeVarSI[n];
3199 :
3200 : for( size_t f = 0; f < m_goptCurrent[n].f_size(); ++f )
3201 : {
3202 : m_clXferLP( f, n ) = m_clXferSI( f, n );
3203 : }
3204 :
3205 : ++m_timesOnLP[n];
3206 : }
3207 : else
3208 : {
3209 : MGO_BREADCRUMB;
3210 : for( size_t f = 0; f < m_goptCurrent[n].f_size(); ++f )
3211 : {
3212 : m_clXferLP( f, n ) = m_goptLP[n].clETF2( f, m_optGainLP[n] );
3213 : }
3214 :
3215 : ++m_timesOnLP[n];
3216 : }
3217 : }
3218 : else
3219 : {
3220 : #pragma omp critical
3221 : {
3222 : ++offLP;
3223 : }
3224 :
3225 : MGO_BREADCRUMB;
3226 : m_optGainLP[n] = 0;
3227 :
3228 : ++m_regCounter[n];
3229 :
3230 : for( size_t f = 0; f < m_goptCurrent[n].f_size(); ++f )
3231 : {
3232 : m_clXferLP( f, n ) = 1;
3233 : }
3234 :
3235 : m_timesOnLP[n] = 0;
3236 : }
3237 :
3238 : MGO_BREADCRUMB;
3239 : }
3240 :
3241 : MGO_BREADCRUMB;
3242 :
3243 0 : m_modesOnSI = m_nModes - off;
3244 0 : m_modesOnLP = m_nModes - offLP;
3245 :
3246 :
3247 :
3248 :
3249 0 : if( m_updating )
3250 : {
3251 0 : continue; // don't break b/c of omp
3252 : }
3253 :
3254 0 : timePointT t1 = std::chrono::steady_clock::now();
3255 0 : durationT dt = t1 - t0;
3256 :
3257 0 : std::cerr << "Optimization took " << dt.count() << " seconds\n";
3258 :
3259 : /*float totVar = 0;
3260 : for( size_t n = 0; n < m_modeVarSI.size(); ++n )
3261 : {
3262 : totVar += m_modeVarSI[n];
3263 : }*/
3264 :
3265 : // std::cerr << "total variance: " << totVar << '\n';
3266 :
3267 0 : float *f = m_optGainStream->array.F;
3268 0 : float *fSI = m_optGainSIStream->array.F;
3269 0 : float *fmaxSI = m_maxGainSIStream->array.F;
3270 0 : float *fLP = m_optGainLPStream->array.F;
3271 0 : float *fmaxLP = m_optGainLPStream->array.F;
3272 :
3273 0 : mx::improc::eigenMap<float> mvs( m_modevarStream->array.F, 3, m_modeVarSI.size() );
3274 :
3275 0 : m_optGainStream->md->write = 1;
3276 0 : m_optGainSIStream->md->write = 1;
3277 0 : m_maxGainSIStream->md->write = 1;
3278 0 : m_optGainLPStream->md->write = 1;
3279 0 : m_maxGainLPStream->md->write = 1;
3280 0 : m_modevarStream->md->write = 1;
3281 :
3282 0 : for( size_t n = 0; n < m_optGainSI.size(); ++n )
3283 : {
3284 : // if( m_timesOnSI[n] > 5 )
3285 : {
3286 0 : f[n] = ( m_gainCalFacts[n] * m_optGainSI[n] / m_gainCals[n] ) / m_opticalGain;
3287 0 : fSI[n] = f[n];
3288 0 : fmaxSI[n] = ( m_gainCalFacts[n] * m_gmaxSI[n] / m_gainCals[n] ) / m_opticalGain;
3289 : }
3290 :
3291 : // if( m_timesOnLP[n] > 5 )
3292 : {
3293 0 : fLP[n] = ( m_gainCalFacts[n] * m_optGainLP[n] / m_gainCals[n] ) / m_opticalGain;
3294 0 : fmaxLP[n] = ( m_gainCalFacts[n] * m_gmaxLP[n] / m_gainCals[n] ) / m_opticalGain;
3295 : }
3296 :
3297 0 : mvs( 0, n ) = m_modeVarOL[n];
3298 0 : mvs( 1, n ) = m_modeVarSI[n];
3299 0 : mvs( 2, n ) = m_modeVarLP[n];
3300 : }
3301 :
3302 0 : ImageStreamIO_UpdateIm( m_optGainStream );
3303 0 : ImageStreamIO_UpdateIm( m_optGainSIStream );
3304 0 : ImageStreamIO_UpdateIm( m_maxGainSIStream );
3305 0 : ImageStreamIO_UpdateIm( m_optGainLPStream );
3306 0 : ImageStreamIO_UpdateIm( m_maxGainLPStream );
3307 0 : ImageStreamIO_UpdateIm( m_modevarStream );
3308 :
3309 0 : if( m_autoUpdate || m_updateOnce || m_dump )
3310 : {
3311 0 : float *f = gainFactShmimMonitorT::m_imageStream.array.F;
3312 :
3313 0 : gainFactShmimMonitorT::m_imageStream.md->write = 1;
3314 0 : if( m_dump )
3315 : {
3316 0 : for( size_t n = 0; n < m_nModes; ++n )
3317 : {
3318 : // if( m_timesOnSI[n] > 5 )
3319 : {
3320 0 : f[n] = ( m_gainCalFacts[n] * m_optGainSI[n] / m_gainCals[n] ) / m_opticalGain;
3321 : }
3322 : }
3323 : }
3324 : else
3325 : {
3326 0 : for( size_t n = 0; n < m_nModes; ++n )
3327 : {
3328 : // if( m_timesOnSI[n] > 5 )
3329 : {
3330 0 : f[n] = f[n] + m_gainGain *
3331 0 : ( ( m_gainCalFacts[n] * m_optGainSI[n] / m_gainCals[n] ) / m_opticalGain -
3332 0 : f[n] );
3333 : }
3334 : }
3335 : }
3336 :
3337 0 : ImageStreamIO_UpdateIm( &( gainFactShmimMonitorT::m_imageStream ) );
3338 :
3339 0 : if( m_doPCCalcs )
3340 : {
3341 0 : float *fpc = pcGainFactShmimMonitorT::m_imageStream.array.F;
3342 0 : float *fa = acoeffShmimMonitorT::m_imageStream.array.F;
3343 0 : float *fb = bcoeffShmimMonitorT::m_imageStream.array.F;
3344 :
3345 0 : pcGainFactShmimMonitorT::m_imageStream.md->write = 1;
3346 0 : acoeffShmimMonitorT::m_imageStream.md->write = 1;
3347 0 : bcoeffShmimMonitorT::m_imageStream.md->write = 1;
3348 :
3349 0 : if( m_dump )
3350 : {
3351 0 : for( size_t n = 0; n < m_optGainLP.size(); ++n )
3352 : {
3353 : // if( m_timesOnLP[n] > 5 )
3354 : {
3355 0 : fpc[n] = ( m_gainCalFacts[n] * m_optGainLP[n] / m_gainCals[n] ) / m_opticalGain;
3356 :
3357 : // To be safe we treat this as if Na and Nb can be different, but they can't be.
3358 0 : fa[n] = m_Na[n];
3359 0 : fb[n] = m_Nb[n];
3360 0 : for( uint32_t k = 0; k < m_Na[n]; ++k )
3361 : {
3362 0 : fa[1 + k] = m_goptLP[n].a()[k];
3363 : }
3364 0 : for( uint32_t k = m_Na[n]; k < acoeffShmimMonitorT::m_width - 1; ++k )
3365 : {
3366 0 : fa[1 + k] = 0;
3367 : }
3368 :
3369 0 : for( uint32_t k = 0; k < m_Nb[n]; ++k )
3370 : {
3371 0 : fb[1 + k] = m_goptLP[n].b()[k];
3372 : }
3373 0 : for( uint32_t k = m_Nb[n]; k < bcoeffShmimMonitorT::m_width - 1; ++k )
3374 : {
3375 0 : fb[1 + k] = 0;
3376 : }
3377 : }
3378 : }
3379 : }
3380 : else
3381 : {
3382 0 : for( size_t n = 0; n < m_optGainSI.size(); ++n )
3383 : {
3384 : // if( m_timesOnLP[n] > 5 )
3385 : {
3386 0 : fpc[n] = fpc[n] +
3387 0 : m_gainGain *
3388 0 : ( ( m_gainCalFacts[n] * m_optGainLP[n] / m_gainCals[n] ) / m_opticalGain -
3389 0 : fpc[n] );
3390 :
3391 : // To be safe we treat this as if Na and Nb can be different, but they can't be.
3392 0 : fa[n] = m_Na[n];
3393 0 : fb[n] = m_Nb[n];
3394 0 : for( uint32_t k = 0; k < m_Na[n]; ++k )
3395 : {
3396 0 : fa[1 + k] = fa[1 + k] + m_gainGain * ( m_goptLP[n].a()[k] - fa[1 + k] );
3397 : }
3398 0 : for( uint32_t k = m_Na[n]; k < acoeffShmimMonitorT::m_width - 1; ++k )
3399 : {
3400 0 : fa[1 + k] = 0;
3401 : }
3402 :
3403 0 : for( uint32_t k = 0; k < m_Nb[n]; ++k )
3404 : {
3405 0 : fb[1 + k] = fb[1 + k] + m_gainGain * ( m_goptLP[n].b()[k] - fb[1 + k] );
3406 : }
3407 0 : for( uint32_t k = m_Nb[n]; k < bcoeffShmimMonitorT::m_width - 1; ++k )
3408 : {
3409 0 : fb[1 + k] = 0;
3410 : }
3411 : }
3412 : }
3413 : }
3414 :
3415 0 : ImageStreamIO_UpdateIm( &( pcGainFactShmimMonitorT::m_imageStream ) );
3416 0 : ImageStreamIO_UpdateIm( &( acoeffShmimMonitorT::m_imageStream ) );
3417 0 : ImageStreamIO_UpdateIm( &( bcoeffShmimMonitorT::m_imageStream ) );
3418 : }
3419 :
3420 0 : if( m_dump )
3421 : {
3422 0 : log<text_log>( "gains updated by dump", logPrio::LOG_NOTICE );
3423 0 : m_dump = false;
3424 : }
3425 0 : else if( m_updateOnce && !m_autoUpdate )
3426 : {
3427 0 : log<text_log>( "gains updated once", logPrio::LOG_NOTICE );
3428 : }
3429 :
3430 0 : m_updateOnce = false;
3431 : }
3432 :
3433 0 : if( m_loop & m_autoUpdate )
3434 : {
3435 0 : m_sinceChange = -1;
3436 : }
3437 :
3438 : // Update OL PSDs and Transfer Functions
3439 0 : m_olPSDStream->md->write = 1;
3440 0 : m_noisePSDStream->md->write = 1;
3441 0 : m_clXferCurrentStream->md->write = 1;
3442 0 : m_clXferSIStream->md->write = 1;
3443 0 : m_clXferLPStream->md->write = 1;
3444 :
3445 0 : for( size_t q = 0; q < m_olPSDs.size(); ++q )
3446 : {
3447 0 : memcpy( m_olPSDStream->array.F + q * m_olPSDs[0].size(),
3448 0 : m_olPSDs[q].data(),
3449 0 : m_olPSDs[0].size() * sizeof( float ) );
3450 :
3451 : // m_noisePSDStream->array.F[q] = m_nPSDs[q][0];
3452 0 : memcpy( m_noisePSDStream->array.F + q * m_nPSDs[0].size(),
3453 0 : m_nPSDs[q].data(),
3454 0 : m_nPSDs[0].size() * sizeof( float ) );
3455 : }
3456 :
3457 0 : memcpy( m_clXferCurrentStream->array.F,
3458 0 : m_clXferCurrent.data(),
3459 0 : m_clXferCurrent.rows() * m_clXferCurrent.cols() * sizeof( float ) );
3460 0 : memcpy(
3461 0 : m_clXferSIStream->array.F, m_clXferSI.data(), m_clXferSI.rows() * m_clXferSI.cols() * sizeof( float ) );
3462 0 : memcpy(
3463 0 : m_clXferLPStream->array.F, m_clXferLP.data(), m_clXferLP.rows() * m_clXferLP.cols() * sizeof( float ) );
3464 :
3465 0 : ImageStreamIO_UpdateIm( m_olPSDStream );
3466 0 : ImageStreamIO_UpdateIm( m_noisePSDStream );
3467 0 : ImageStreamIO_UpdateIm( m_clXferCurrentStream );
3468 0 : ImageStreamIO_UpdateIm( m_clXferSIStream );
3469 0 : ImageStreamIO_UpdateIm( m_clXferLPStream );
3470 0 : }
3471 : else
3472 : {
3473 : /* Check for why we timed out */
3474 : /* ETIMEDOUT just means keep waiting */
3475 0 : if( errno == ETIMEDOUT )
3476 : {
3477 : // Could Update gopts if needed (requires size checks and requires mutex lock)
3478 : // Probably not worth it for pred. control anyway.
3479 0 : continue;
3480 : }
3481 :
3482 : /* EINTER probably indicates time to shutdown, loop wil exit if m_shutdown is set */
3483 0 : if( errno == EINTR )
3484 : {
3485 0 : continue;
3486 : }
3487 :
3488 : /*Otherwise, report an error.*/
3489 0 : log<software_error>( { __FILE__, __LINE__, errno, "sem_timedwait" } );
3490 0 : break;
3491 : }
3492 : }
3493 : }
3494 :
3495 0 : INDI_NEWCALLBACK_DEFN( modalGainOpt, m_indiP_autoUpdate )( const pcf::IndiProperty &ipRecv )
3496 : {
3497 0 : INDI_VALIDATE_CALLBACK_PROPS( m_indiP_autoUpdate, ipRecv );
3498 :
3499 0 : if( ipRecv.find( "toggle" ) )
3500 : {
3501 0 : if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On )
3502 : {
3503 0 : if( !m_autoUpdate )
3504 : {
3505 0 : log<text_log>( "updating gains", logPrio::LOG_NOTICE );
3506 : }
3507 0 : m_autoUpdate = true;
3508 : }
3509 : else
3510 : {
3511 0 : if( m_autoUpdate )
3512 : {
3513 0 : log<text_log>( "stopped updating gains", logPrio::LOG_NOTICE );
3514 : }
3515 0 : m_autoUpdate = false;
3516 : }
3517 : }
3518 :
3519 0 : return 0;
3520 : }
3521 :
3522 0 : INDI_NEWCALLBACK_DEFN( modalGainOpt, m_indiP_updateOnce )( const pcf::IndiProperty &ipRecv )
3523 : {
3524 0 : INDI_VALIDATE_CALLBACK_PROPS( m_indiP_updateOnce, ipRecv );
3525 :
3526 0 : if( ipRecv.find( "request" ) )
3527 : {
3528 0 : if( ipRecv["request"].getSwitchState() == pcf::IndiElement::On )
3529 : {
3530 0 : m_updateOnce = true;
3531 : }
3532 : else
3533 : {
3534 0 : m_updateOnce = false;
3535 : }
3536 : }
3537 :
3538 0 : return 0;
3539 : }
3540 :
3541 0 : INDI_NEWCALLBACK_DEFN( modalGainOpt, m_indiP_dump )( const pcf::IndiProperty &ipRecv )
3542 : {
3543 0 : INDI_VALIDATE_CALLBACK_PROPS( m_indiP_dump, ipRecv );
3544 :
3545 0 : if( ipRecv.find( "request" ) )
3546 : {
3547 0 : if( ipRecv["request"].getSwitchState() == pcf::IndiElement::On )
3548 : {
3549 0 : m_dump = true;
3550 : }
3551 : else
3552 : {
3553 0 : m_dump = false;
3554 : }
3555 : }
3556 :
3557 0 : return 0;
3558 : }
3559 :
3560 0 : INDI_NEWCALLBACK_DEFN( modalGainOpt, m_indiP_opticalGain )( const pcf::IndiProperty &ipRecv )
3561 : {
3562 0 : INDI_VALIDATE_CALLBACK_PROPS( m_indiP_opticalGain, ipRecv );
3563 :
3564 : float target;
3565 0 : if( indiTargetUpdate( m_indiP_opticalGain, target, ipRecv, true ) < 0 )
3566 : {
3567 0 : log<software_error>( { __FILE__, __LINE__ } );
3568 0 : return -1;
3569 : }
3570 :
3571 0 : m_opticalGain = target;
3572 :
3573 0 : return 0;
3574 : }
3575 :
3576 0 : INDI_NEWCALLBACK_DEFN( modalGainOpt, m_indiP_opticalGainUpdate )( const pcf::IndiProperty &ipRecv )
3577 : {
3578 0 : INDI_VALIDATE_CALLBACK_PROPS( m_indiP_opticalGainUpdate, ipRecv );
3579 :
3580 0 : if(ipRecv.find("toggle"))
3581 : {
3582 0 : if(ipRecv["toggle"].getSwitchState() == pcf::IndiElement::Off)
3583 : {
3584 0 : m_opticalGainUpdate = false;
3585 : }
3586 : else
3587 : {
3588 0 : m_opticalGainUpdate = true;
3589 :
3590 0 : if(m_opticalGainSource > 0 && m_opticalGainSource < 1)
3591 : {
3592 0 : m_opticalGain = m_opticalGainSource;
3593 : }
3594 : }
3595 : }
3596 :
3597 0 : return 0;
3598 : }
3599 :
3600 0 : INDI_SETCALLBACK_DEFN( modalGainOpt, m_indiP_opticalGainSource )( const pcf::IndiProperty &ipRecv )
3601 : {
3602 0 : INDI_VALIDATE_CALLBACK_PROPS( m_indiP_opticalGainSource, ipRecv );
3603 :
3604 0 : if( ipRecv.find( m_opticalGainElement ) )
3605 : {
3606 0 : float opticalg = ipRecv[m_opticalGainElement].get<float>();
3607 :
3608 0 : opticalg = (floor(opticalg * 100 + 0.5))/100.;
3609 :
3610 0 : if(opticalg > 0 && opticalg < 1)
3611 : {
3612 0 : m_opticalGainSource = opticalg;
3613 : }
3614 :
3615 0 : if(m_opticalGainUpdate)
3616 : {
3617 0 : m_opticalGain = m_opticalGainSource;
3618 : }
3619 : }
3620 0 : return 0;
3621 : }
3622 :
3623 0 : INDI_NEWCALLBACK_DEFN( modalGainOpt, m_indiP_gainGain )( const pcf::IndiProperty &ipRecv )
3624 : {
3625 0 : INDI_VALIDATE_CALLBACK_PROPS( m_indiP_gainGain, ipRecv );
3626 :
3627 : float target;
3628 0 : if( indiTargetUpdate( m_indiP_gainGain, target, ipRecv, true ) < 0 )
3629 : {
3630 0 : log<software_error>( { __FILE__, __LINE__ } );
3631 0 : return -1;
3632 : }
3633 :
3634 0 : m_gainGain = target;
3635 :
3636 0 : return 0;
3637 : }
3638 :
3639 0 : INDI_SETCALLBACK_DEFN( modalGainOpt, m_indiP_emg )( const pcf::IndiProperty &ipRecv )
3640 : {
3641 0 : INDI_VALIDATE_CALLBACK_PROPS( m_indiP_emg, ipRecv );
3642 :
3643 0 : if( ipRecv.find( "current" ) )
3644 : {
3645 0 : float emg = ipRecv["current"].get<float>();
3646 :
3647 0 : if( emg != m_emg )
3648 : {
3649 0 : m_emg = emg;
3650 0 : std::cerr << "Got EMG: " << m_emg << '\n';
3651 : }
3652 : }
3653 0 : return 0;
3654 : }
3655 :
3656 0 : INDI_SETCALLBACK_DEFN( modalGainOpt, m_indiP_psdTime )( const pcf::IndiProperty &ipRecv )
3657 : {
3658 0 : INDI_VALIDATE_CALLBACK_PROPS( m_indiP_psdTime, ipRecv );
3659 :
3660 0 : if( ipRecv.find( "current" ) )
3661 : {
3662 0 : float psdTime = ipRecv["current"].get<float>();
3663 :
3664 0 : if( psdTime != m_psdTime )
3665 : {
3666 0 : m_updating = true;
3667 0 : std::lock_guard<std::mutex> lock( m_goptMutex );
3668 0 : m_updating = true;
3669 :
3670 0 : m_psdTime = psdTime;
3671 :
3672 0 : m_sinceChange = -1;
3673 0 : m_updating = false;
3674 :
3675 0 : std::cerr << "Got psdTime: " << m_psdTime << '\n';
3676 0 : }
3677 : }
3678 0 : return 0;
3679 : }
3680 :
3681 0 : INDI_SETCALLBACK_DEFN( modalGainOpt, m_indiP_psdAvgTime )( const pcf::IndiProperty &ipRecv )
3682 : {
3683 0 : INDI_VALIDATE_CALLBACK_PROPS( m_indiP_psdAvgTime, ipRecv );
3684 :
3685 0 : if( ipRecv.find( "current" ) )
3686 : {
3687 0 : float psdAvgTime = ipRecv["current"].get<float>();
3688 :
3689 0 : if( psdAvgTime != m_psdAvgTime )
3690 : {
3691 0 : m_updating = true;
3692 0 : std::lock_guard<std::mutex> lock( m_goptMutex );
3693 0 : m_updating = true;
3694 :
3695 0 : m_psdAvgTime = psdAvgTime;
3696 :
3697 0 : m_sinceChange = -1;
3698 0 : m_updating = false;
3699 :
3700 0 : std::cerr << "Got psdAvgTime: " << m_psdAvgTime << '\n';
3701 0 : }
3702 : }
3703 :
3704 0 : return 0;
3705 : }
3706 :
3707 0 : INDI_SETCALLBACK_DEFN( modalGainOpt, m_indiP_loop )( const pcf::IndiProperty &ipRecv )
3708 : {
3709 0 : INDI_VALIDATE_CALLBACK_PROPS( m_indiP_loop, ipRecv );
3710 :
3711 0 : if( ipRecv.find( "toggle" ) )
3712 : {
3713 : bool state;
3714 :
3715 0 : if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On )
3716 : {
3717 0 : state = true;
3718 : }
3719 : else
3720 : {
3721 0 : state = false;
3722 : }
3723 :
3724 0 : if( state != m_loop )
3725 : {
3726 0 : m_updating = true;
3727 0 : std::lock_guard<std::mutex> lock( m_goptMutex );
3728 0 : m_updating = true;
3729 :
3730 0 : m_loop = state;
3731 :
3732 0 : if( !m_loop )
3733 : {
3734 0 : m_autoUpdate = false;
3735 0 : m_dump = false;
3736 : }
3737 :
3738 0 : m_sinceChange = -1;
3739 0 : m_updating = false;
3740 0 : std::cerr << "Got loop: " << m_loop << '\n';
3741 0 : }
3742 : }
3743 :
3744 0 : return 0;
3745 : }
3746 :
3747 0 : INDI_SETCALLBACK_DEFN( modalGainOpt, m_indiP_siGain )( const pcf::IndiProperty &ipRecv )
3748 : {
3749 0 : INDI_VALIDATE_CALLBACK_PROPS( m_indiP_siGain, ipRecv );
3750 :
3751 0 : if( ipRecv.find( "current" ) )
3752 : {
3753 0 : float gain = ipRecv["current"].get<float>();
3754 :
3755 0 : if( gain != m_gain && !m_pcOn )
3756 : {
3757 0 : m_updating = true;
3758 0 : std::lock_guard<std::mutex> lock( m_goptMutex );
3759 0 : m_updating = true;
3760 :
3761 0 : m_gain = gain;
3762 :
3763 0 : if( m_loop )
3764 : {
3765 0 : m_sinceChange = -1;
3766 : }
3767 :
3768 0 : m_updating = false;
3769 :
3770 0 : std::cerr << "Got gain: " << m_gain << '\n';
3771 0 : }
3772 : else
3773 : {
3774 0 : m_gain = gain; // for the m_pcOn case
3775 : }
3776 : }
3777 :
3778 0 : return 0;
3779 : }
3780 :
3781 0 : INDI_SETCALLBACK_DEFN( modalGainOpt, m_indiP_siMult )( const pcf::IndiProperty &ipRecv )
3782 : {
3783 0 : INDI_VALIDATE_CALLBACK_PROPS( m_indiP_siMult, ipRecv );
3784 :
3785 0 : if( ipRecv.find( "current" ) )
3786 : {
3787 0 : float mc = ipRecv["current"].get<float>();
3788 :
3789 0 : if( mc != m_mult && !m_pcOn )
3790 : {
3791 0 : m_updating = true;
3792 0 : std::lock_guard<std::mutex> lock( m_goptMutex );
3793 0 : m_updating = true;
3794 :
3795 0 : m_mult = mc;
3796 :
3797 0 : if( m_loop )
3798 : {
3799 0 : m_sinceChange = -1;
3800 : }
3801 :
3802 0 : m_goptUpdated = true;
3803 0 : m_updating = false;
3804 0 : std::cerr << "Got mc: " << m_mult << '\n';
3805 0 : }
3806 : else
3807 : {
3808 0 : m_mult = mc; // for the m_pcOn case
3809 : }
3810 : }
3811 :
3812 0 : return 0;
3813 : }
3814 :
3815 0 : INDI_SETCALLBACK_DEFN( modalGainOpt, m_indiP_pcGain )( const pcf::IndiProperty &ipRecv )
3816 : {
3817 0 : INDI_VALIDATE_CALLBACK_PROPS( m_indiP_pcGain, ipRecv );
3818 :
3819 0 : if( ipRecv.find( "current" ) )
3820 : {
3821 0 : float gain = ipRecv["current"].get<float>();
3822 :
3823 0 : if( gain != m_pcGain && m_pcOn )
3824 : {
3825 0 : m_updating = true;
3826 0 : std::lock_guard<std::mutex> lock( m_goptMutex );
3827 0 : m_updating = true;
3828 :
3829 0 : m_pcGain = gain;
3830 :
3831 0 : if( m_loop )
3832 : {
3833 0 : m_sinceChange = -1;
3834 : }
3835 :
3836 0 : m_updating = false;
3837 :
3838 0 : std::cerr << "Got pc gain: " << m_pcGain << '\n';
3839 0 : }
3840 : else
3841 : {
3842 0 : m_pcGain = gain; // for the !m_pcOn case
3843 : }
3844 : }
3845 :
3846 0 : return 0;
3847 : }
3848 :
3849 0 : INDI_SETCALLBACK_DEFN( modalGainOpt, m_indiP_pcMult )( const pcf::IndiProperty &ipRecv )
3850 : {
3851 0 : INDI_VALIDATE_CALLBACK_PROPS( m_indiP_pcMult, ipRecv );
3852 :
3853 0 : if( ipRecv.find( "current" ) )
3854 : {
3855 0 : float mc = ipRecv["current"].get<float>();
3856 :
3857 0 : if( mc != m_pcMult && m_pcOn )
3858 : {
3859 0 : m_updating = true;
3860 0 : std::lock_guard<std::mutex> lock( m_goptMutex );
3861 0 : m_updating = true;
3862 :
3863 0 : m_pcMult = mc;
3864 :
3865 0 : if( m_loop )
3866 : {
3867 0 : m_sinceChange = -1;
3868 : }
3869 :
3870 0 : m_pcgoptUpdated = true;
3871 0 : m_updating = false;
3872 0 : std::cerr << "Got pc mc: " << m_pcMult << '\n';
3873 0 : }
3874 : else
3875 : {
3876 0 : m_pcMult = mc; // for the !m_pcOn case
3877 : }
3878 : }
3879 :
3880 0 : return 0;
3881 : }
3882 :
3883 0 : INDI_SETCALLBACK_DEFN( modalGainOpt, m_indiP_pcOn )( const pcf::IndiProperty &ipRecv )
3884 : {
3885 0 : INDI_VALIDATE_CALLBACK_PROPS( m_indiP_pcOn, ipRecv );
3886 :
3887 0 : if( ipRecv.find( "toggle" ) )
3888 : {
3889 : bool state;
3890 :
3891 0 : if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On )
3892 : {
3893 0 : state = true;
3894 : }
3895 : else
3896 : {
3897 0 : state = false;
3898 : }
3899 :
3900 0 : if( state != m_pcOn )
3901 : {
3902 0 : m_updating = true;
3903 0 : std::lock_guard<std::mutex> lock( m_goptMutex );
3904 0 : m_updating = true;
3905 :
3906 0 : m_pcOn = state;
3907 :
3908 0 : m_sinceChange = -1;
3909 0 : m_updating = false;
3910 0 : std::cerr << "Got pcOn: " << std::boolalpha << m_pcOn << '\n';
3911 0 : }
3912 : }
3913 :
3914 0 : return 0;
3915 : }
3916 :
3917 0 : INDI_NEWCALLBACK_DEFN( modalGainOpt, m_indiP_extrapOL )( const pcf::IndiProperty &ipRecv )
3918 : {
3919 0 : INDI_VALIDATE_CALLBACK_PROPS( m_indiP_extrapOL, ipRecv );
3920 :
3921 0 : if( ipRecv.find( "toggle" ) )
3922 : {
3923 : int ext;
3924 :
3925 0 : if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On )
3926 : {
3927 0 : ext = true;
3928 : }
3929 : else
3930 : {
3931 0 : ext = false;
3932 : }
3933 :
3934 0 : if( ext != m_extrapOL )
3935 : {
3936 0 : m_updating = true;
3937 0 : std::lock_guard<std::mutex> lock( m_goptMutex );
3938 0 : m_updating = true;
3939 :
3940 0 : m_extrapOL = ext;
3941 :
3942 0 : m_sinceChange = -1;
3943 0 : m_updating = false;
3944 0 : std::cerr << "Got extrap: " << m_extrapOL << '\n';
3945 0 : }
3946 : }
3947 :
3948 0 : return 0;
3949 : }
3950 : } // namespace app
3951 : } // namespace MagAOX
3952 :
3953 : #endif // modalGainOpt_hpp
|