11 #include "../../libMagAOX/libMagAOX.hpp"
12 #include "../../magaox_git_version.h"
14 #include <mx/sigproc/circularBuffer.hpp>
15 #include <mx/sigproc/signalWindows.hpp>
17 #include <mx/math/fft/fftwEnvironment.hpp>
18 #include <mx/math/fft/fft.hpp>
58 typedef mx::sigproc::circularBufferIndex<float*, unsigned>
ampCircBuffT;
104 mx::math::fft::fftT< realT, std::complex<realT>, 1, 0>
m_fft;
216 config.add(
"circBuff.fpsSource",
"",
"circBuff.fpsSource", argType::Required,
"circBuff",
"fpsSource",
false,
"string",
"Device name for getting fps to set circular buffer length. This device should have *.fps.current.");
217 config.add(
"circBuff.defaultFPS",
"",
"circBuff.defaultFPS", argType::Required,
"circBuff",
"defaultFPS",
false,
"realT",
"Default FPS at startup, will enable changing average length with psdTime before INDI available.");
218 config.add(
"circBuff.psdTime",
"",
"circBuff.psdTime", argType::Required,
"circBuff",
"psdTime",
false,
"realT",
"The length of time over which to calculate PSDs. The default is 1 sec.");
226 _config(
m_fps,
"circBuff.defaultFPS");
311 static_cast<void>(dummy);
329 log<software_error>({ __FILE__,__LINE__,
"bad m_tsOverlapSize value: " + std::to_string(
m_tsOverlapSize) });
337 log<software_error>({ __FILE__,__LINE__,
"unsupported data type: must be realT" });
345 log<software_error>({ __FILE__,__LINE__,
"unexpected shmim format" });
359 mx::sigproc::window::hann(
m_win);
386 imsize[1] =
m_psd.size();
394 m_freqStream =
static_cast<IMAGE*
>(malloc(
sizeof(IMAGE)));
396 ImageStreamIO_createIm_gpu(
m_freqStream, (
m_configName +
"_freq").c_str(), 3, imsize,
IMAGESTRUCT_FLOAT, -1, 1, IMAGE_NB_SEMAPHORE, 0, CIRCULAR_BUFFER | ZAXIS_TEMPORAL, 0);
398 for (
size_t n = 0; n <
m_psd.size(); ++n)
404 clock_gettime(CLOCK_REALTIME, &
m_freqStream->md->writetime);
432 imsize[0] =
m_psd.size();
438 ImageStreamIO_createIm_gpu(
m_rawpsdStream, (
m_configName +
"_rawpsds").c_str(), 3, imsize,
IMAGESTRUCT_FLOAT, -1, 1, IMAGE_NB_SEMAPHORE, 0, CIRCULAR_BUFFER | ZAXIS_TEMPORAL, 0);
446 imsize[0] =
m_psd.size();
451 ImageStreamIO_createIm_gpu(
m_avgpsdStream, (
m_configName +
"_psds").c_str(), 3, imsize,
IMAGESTRUCT_FLOAT, -1, 1, IMAGE_NB_SEMAPHORE, 0, CIRCULAR_BUFFER | ZAXIS_TEMPORAL, 0);
462 static_cast<void>(dummy);
464 float* f_src =
static_cast<float*
>(curr_src);
498 log<software_error>({ __FILE__, __LINE__,
"amp circ buff has zero size" });
510 std::cerr <<
"all grown. starting to calculate\n";
512 ampCircBuffT::indexT ne0;
526 double t0 = mx::sys::get_curr_time();
539 for (
size_t n = 0; n <
m_tsSize; ++n)
551 for (
size_t n = 0; n <
m_psd.size(); ++n)
557 for (
size_t n = 0; n <
m_psd.size(); ++n)
559 m_psd[n] *= (var / nm);
595 if (nPSDAverage <= 0) nPSDAverage = 1;
603 for (
int n = 1; n < nPSDAverage; ++n)
635 double t1 = mx::sys::get_curr_time();
657 if (ce >= ne1) dn = ce - ne1;
662 double stime = (1.0 * dn) /
m_fps * 0.5 * 1e9;
667 if (ce >= ne1) dn = ce - ne1;
680 if (indiTargetUpdate(m_indiP_psdTime, target,
ipRecv,
true) < 0)
682 log<software_error>({ __FILE__,__LINE__ });
686 if (m_psdTime != target)
688 std::lock_guard<std::mutex> guard(m_indiMutex);
695 shmimMonitorT::m_restart =
true;
709 if (indiTargetUpdate(m_indiP_psdAvgTime, target,
ipRecv,
true) < 0)
711 log<software_error>({ __FILE__,__LINE__ });
715 if (m_psdAvgTime != target)
717 std::lock_guard<std::mutex> guard(m_indiMutex);
719 m_psdAvgTime = target;
734 if (
ipRecv.find(
"current") !=
true)
736 log<software_error>({ __FILE__, __LINE__,
"No current property in fps source." });
740 std::lock_guard<std::mutex> guard(m_indiMutex);
742 realT fps =
ipRecv[
"current"].get<realT>();
749 shmimMonitorT::m_restart =
true;
#define IMAGESTRUCT_FLOAT
#define XWCAPP_THREAD_CHECK(thrdSt, thrdName)
Error handling wrapper for checking on thread status with tryjoin.
#define XWCAPP_THREAD_START(thrdSt, thrdInit, thrdId, thrdProp, thrdPrio, thrdCpuset, thrdName, thrdStart)
Error handling wrapper for the threadStart function of the XWCApp.
#define XWCAPP_THREAD_STOP(thrdSt)
Error handlng wrapper for stopping a thread.
The base-class for MagAO-X applications.
std::string m_configName
The name of the configuration file (minus .conf).
stateCodes::stateCodeT state()
Get the current state code.
int shutdown()
Get the value of the shutdown flag.
std::mutex m_indiMutex
Mutex for locking INDI communications.
uint32_t m_depth
The depth of the circular buffer in the stream.
uint32_t m_width
The width of the images in the stream.
uint32_t m_height
The height of the images in the stream.
std::string m_shmimName
The name of the shared memory image, is used in /tmp/<shmimName>.im.shm. Derived classes should set a...
uint8_t m_dataType
The ImageStreamIO type code.
Class for application to calculate rolling PSDs of modal amplitudes.
realT m_psdOverlapFraction
The fraction of the sample time to overlap by.
pcf::IndiProperty m_psdThreadProp
The property to hold the PSD Calculation thread details.
pcf::IndiProperty m_indiP_psdAvgTime
INDI_NEWCALLBACK_DECL(modalPSDs, m_indiP_overSize)
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
pid_t m_psdThreadID
PSD Calculation thread PID.
mx::improc::eigenImage< realT > m_psdBuffer
std::thread m_psdThread
The PSD Calculation thread.
pcf::IndiProperty m_indiP_overSize
unsigned m_tsOverlapSize
The number of samples in the overlap.
std::complex< realT > * m_fftWork
mx::math::fft::fftwEnvironment< realT > m_fftEnv
mx::sigproc::circularBufferIndex< float *, unsigned > ampCircBuffT
The amplitude circular buffer type.
INDI_NEWCALLBACK_DECL(modalPSDs, m_indiP_psdTime)
static void psdThreadStart(modalPSDs *p)
PS Calculation thread starter function.
std::vector< realT > m_win
The window function. By default this is Hann.
virtual int appStartup()
Startup function.
INDI_SETCALLBACK_DECL(modalPSDs, m_indiP_fpsSource)
INDI_NEWCALLBACK_DECL(modalPSDs, m_indiP_psdAvgTime)
IMAGE * m_avgpsdStream
The ImageStreamIO shared memory buffer to hold the average psds.
IMAGE * m_rawpsdStream
The ImageStreamIO shared memory buffer to hold the raw psds.
modalPSDs()
Default c'tor.
int m_nModes
the number of modes to calculate PSDs for.
mx::math::fft::fftT< realT, std::complex< realT >, 1, 0 > m_fft
bool m_psdRestarting
Synchronization flag. This will only become false after a successful call to allocate.
virtual void loadConfig()
pcf::IndiProperty m_indiP_fps
virtual int appLogic()
Implementation of the FSM for modalPSDs.
int processImage(void *curr_src, const dev::shmimT &dummy)
IMAGE * m_freqStream
The ImageStreamIO shared memory buffer to hold the frequency scale.
realT m_psdAvgTime
The time over which to average PSDs. The default is 10 sec.
unsigned m_tsSize
The length of the time series sample over which the PSD is calculated.
virtual void setupConfig()
ampCircBuffT m_ampCircBuff
int m_psdThreadPrio
Priority of the PSD Calculation thread.
std::string m_psdThreadCpuset
The cpuset to use for the PSD Calculation thread.
std::complex< realT > complexT
int allocate(const dev::shmimT &dummy)
bool m_psdWaiting
Synchronization flag. This is set to true when the PSD thread is safely waiting for allocation to com...
pcf::IndiProperty m_indiP_psdTime
pcf::IndiProperty m_indiP_fpsSource
realT m_psdTime
The length of time over which to calculate PSDs. The default is 1 sec.
void psdThreadExec()
PSD Calculation thread function.
bool m_psdThreadInit
Initialization flag for the PSD Calculation thread.
virtual int appShutdown()
Shutdown the app.
~modalPSDs() noexcept
D'tor, declared and defined for noexcept.
std::vector< realT > m_psd
dev::shmimMonitor< modalPSDs > shmimMonitorT
The base shmimMonitor type.
std::string m_fpsSource
Device name for getting fps to set circular buffer length. This device should have *....
#define CREATE_REG_INDI_NEW_NUMBERU(prop, name, min, max, step, format, label, group)
Create and register a NEW INDI property as a standard number as unsigned int, using the standard call...
#define CREATE_REG_INDI_NEW_NUMBERF(prop, name, min, max, step, format, label, group)
Create and register a NEW INDI property as a standard number as float, using the standard callback na...
#define REG_INDI_SETPROP(prop, devName, propName)
Register a SET INDI property with the class, using the standard callback name.
#define CREATE_REG_INDI_RO_NUMBER(prop, name, label, group)
Create and register a RO INDI property as a number, using the standard callback name.
@ OPERATING
The device is operating, other than homing.
INDI_VALIDATE_CALLBACK_PROPS(function, ipRecv)
void nanoSleep(unsigned long nsec)
const pcf::IndiProperty & ipRecv
INDI_SETCALLBACK_DEFN(adcTracker, m_indiP_teldata)(const pcf
updateIfChanged(m_indiP_angle, "target", m_angle)
INDI_NEWCALLBACK_DEFN(acesxeCtrl, m_indiP_windspeed)(const pcf
std::unique_lock< std::mutex > lock(m_indiMutex)
constexpr static logPrioT LOG_WARNING
A condition has occurred which may become an error, but the process continues.
constexpr static logPrioT LOG_NOTICE
A normal but significant condition.
#define SHMIMMONITOR_APP_SHUTDOWN
Call shmimMonitorT::appShutdown with error checking for shmimMonitor.
#define SHMIMMONITOR_APP_LOGIC
Call shmimMonitorT::appLogic with error checking for shmimMonitor.
#define SHMIMMONITOR_APP_STARTUP
Call shmimMonitorT::appStartup with error checking for shmimMonitor.
#define SHMIMMONITOR_LOAD_CONFIG(cfig)
Call shmimMonitorT::loadConfig with error checking for shmimMonitor.
#define SHMIMMONITOR_UPDATE_INDI
Call shmimMonitorT::updateINDI with error checking for shmimMonitor.
#define SHMIMMONITOR_SETUP_CONFIG(cfig)
Call shmimMonitorT::setupConfig with error checking for shmimMonitor.