7#ifndef shmimIntegrator_hpp
8#define shmimIntegrator_hpp
12#include <mx/improc/eigenCube.hpp>
13#include <mx/improc/eigenImage.hpp>
15#include "../../libMagAOX/libMagAOX.hpp"
16#include "../../magaox_git_version.h"
339 config.add(
"integrator.nAverage",
"",
"integrator.nAverage", argType::Required,
"integrator",
"nAverage",
false,
"unsigned",
"The default number of frames to average. Default 10. Can be changed via INDI.");
340 config.add(
"integrator.fpsSource",
"",
"integrator.fpsSource", argType::Required,
"integrator",
"fpsSource",
false,
"string",
"Device name for getting fps if time-based averaging is used. This device should have *.fps.current.");
342 config.add(
"integrator.avgTime",
"",
"integrator.avgTime", argType::Required,
"integrator",
"avgTime",
false,
"float",
"If non zero, then m_nAverage adjusts automatically to keep a constant averaging time [sec]. Default 0. Can be changed via INDI.");
344 config.add(
"integrator.nUpdate",
"",
"integrator.nUpdate", argType::Required,
"integrator",
"nUpdate",
false,
"unsigned",
"The rate at which to update the average. If 0 < m_nUpdate < m_nAverage then this is a moving averager. Default 0. If 0, then it is a simple average.");
346 config.add(
"integrator.continuous",
"",
"integrator.continuous", argType::Required,
"integrator",
"continuous",
false,
"bool",
"Flag controlling whether averaging is continuous or only when triggered. Default true.");
347 config.add(
"integrator.running",
"",
"integrator.running", argType::Required,
"integrator",
"running",
false,
"bool",
"Flag controlling whether averaging is running at startup. Default true.");
349 config.add(
"integrator.stateSource",
"",
"integrator.stateSource", argType::Required,
"integrator",
"stateSource",
false,
"string",
"///< Device name for getting the state string for file management. This device should have *.state_string.current.");
350 config.add(
"integrator.fileSaver",
"",
"integrator.fileSaver", argType::Required,
"integrator",
"fileSaver",
false,
"bool",
"Flag controlling whether this saves and reloads files automatically. Default false.");
467 std::stringstream
logss;
627 static_cast<void>(
dummy);
715 static_cast<void>(
dummy);
789 char cts[] =
"YYYYMMDDHHMMSSNNNNNNNNN";
793 if(
rv !=
sizeof(
cts)-1)
801 mx::fits::fitsFile<float>
ff;
873 static_cast<void>(
dummy);
908 static_cast<void>(
dummy);
926 static_cast<void>(
dummy);
961 static_cast<void>(
dummy);
984 for(
long n =
N-1;
n >= 0; --
n)
986 std::string
fn = mx::ioutils::pathStem(
fnames[
n]);
991 size_t ed =
fn.find(
"__T");
992 if(
ed == std::string::npos ||
ed -
st < 2)
continue;
997 mx::fits::fitsFile<float>
ff;
1121 if(
ipRecv.getName() != m_indiP_nAverage.getName())
1123 log<software_error>({__FILE__, __LINE__,
"invalid indi property received"});
1129 if( indiTargetUpdate( m_indiP_nAverage, target,
ipRecv,
true) < 0)
1131 log<software_error>({__FILE__,__LINE__});
1135 m_nAverage = target;
1137 if(m_avgTime > 0 && m_fps > 0)
1139 m_avgTime = m_nAverage/m_fps;
1148 shmimMonitorT::m_restart =
true;
1157 if(
ipRecv.getName() != m_indiP_avgTime.getName())
1159 log<software_error>({__FILE__, __LINE__,
"invalid indi property received"});
1165 if( indiTargetUpdate( m_indiP_avgTime, target,
ipRecv,
true) < 0)
1167 log<software_error>({__FILE__,__LINE__});
1176 shmimMonitorT::m_restart =
true;
1185 if(
ipRecv.getName() != m_indiP_nUpdate.getName())
1187 log<software_error>({__FILE__, __LINE__,
"invalid indi property received"});
1193 if( indiTargetUpdate( m_indiP_nUpdate, target,
ipRecv,
true) < 0)
1195 log<software_error>({__FILE__,__LINE__});
1205 shmimMonitorT::m_restart =
true;
1214 if(
ipRecv.getName() != m_indiP_startAveraging.getName())
1216 log<software_error>({__FILE__, __LINE__,
"invalid indi property received"});
1220 if(!
ipRecv.find(
"toggle"))
return 0;
1222 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::Off)
1224 std::unique_lock<std::mutex>
lock(m_indiMutex);
1230 updateSwitchIfChanged(m_indiP_startAveraging,
"toggle", pcf::IndiElement::Off,
INDI_IDLE);
1233 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On)
1235 std::unique_lock<std::mutex>
lock(m_indiMutex);
1237 if(m_fileSaver && !m_continuous) m_stateStringChanged =
false;
1239 m_stateStringValidOnStart = m_stateStringValid;
1244 updateSwitchIfChanged(m_indiP_startAveraging,
"toggle", pcf::IndiElement::On,
INDI_BUSY);
1251 if(
ipRecv.getName() != m_indiP_fpsSource.getName())
1253 log<software_error>({__FILE__, __LINE__,
"Invalid INDI property."});
1257 if(
ipRecv.find(
"current") !=
true )
1262 std::lock_guard<std::mutex> guard(m_indiMutex);
1264 realT fps =
ipRecv[
"current"].get<
float>();
1269 std::cout <<
"Got fps: " << m_fps <<
"\n";
1270 shmimMonitorT::m_restart =
true;
1278 if(
ipRecv.getName() != m_indiP_stateSource.getName())
1280 log<software_error>({__FILE__, __LINE__,
"Invalid INDI property."});
1284 if(
ipRecv.find(
"valid") ==
true )
1286 bool stateStringValid;
1287 if(
ipRecv[
"valid"].get<std::string>() ==
"yes") stateStringValid =
true;
1288 else stateStringValid =
false;
1290 if(stateStringValid != m_stateStringValid) m_stateStringChanged =
true;
1292 m_stateStringValid = stateStringValid;
1295 if(
ipRecv.find(
"current") !=
true )
1302 std::lock_guard<std::mutex> guard(m_indiMutex);
1304 std::string ss =
ipRecv[
"current"].get<std::string>();
1306 if(ss != m_stateString)
1309 m_imageValid =
false;
1311 m_stateStringChanged =
true;
The base-class for MagAO-X applications.
void updateIfChanged(pcf::IndiProperty &p, const std::string &el, const T &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI property element value if it has changed.
std::string m_configName
The name of the configuration file (minus .conf).
stateCodes::stateCodeT state()
Get the current state code.
int registerIndiPropertyNew(pcf::IndiProperty &prop, int(*)(void *, const pcf::IndiProperty &))
Register an INDI property which is exposed for others to request a New Property for.
int createStandardIndiToggleSw(pcf::IndiProperty &prop, const std::string &name, const std::string &label="", const std::string &group="")
Create a standard R/W INDI switch with a single toggle element.
void updateSwitchIfChanged(pcf::IndiProperty &p, const std::string &el, const pcf::IndiElement::SwitchStateType &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI switch element value if it has changed.
std::string m_calibDir
The path to calibration files for MagAOX.
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
int registerIndiPropertyReadOnly(pcf::IndiProperty &prop)
Register an INDI property which is read only.
int createROIndiText(pcf::IndiProperty &prop, const std::string &propName, const std::string &elName, const std::string &propLabel="", const std::string &propGroup="", const std::string &elLabel="")
Create a standard ReadOnly INDI Text property, with at least one element.
std::mutex m_indiMutex
Mutex for locking INDI communications.
timespec m_currImageTimestamp
The timestamp of the current image.
uint32_t m_width
The width of the image, once deinterlaced etc.
int appShutdown()
Shuts down the framegrabber thread.
int recordFGTimings(bool force=false)
int loadConfig(mx::app::appConfigurator &config)
load the configuration system results
size_t m_typeSize
The size of the type, in bytes. Result of sizeof.
int updateINDI()
Update the INDI properties for this device controller.
uint8_t m_dataType
The ImageStreamIO type code.
bool m_reconfig
Flag to set if a camera reconfiguration requires a framegrabber reset.
int appLogic()
Checks the framegrabber thread.
int appStartup()
Startup function.
uint32_t m_height
The height of the image, once deinterlaced etc.
int setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
int appStartup()
Startup function.
uint32_t m_width
The width of the images in the stream.
int setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
int updateINDI()
Update the INDI properties for this device controller.
int appLogic()
Checks the shmimMonitor thread.
uint32_t m_height
The height of the images in the stream.
int appShutdown()
Shuts down the shmimMonitor thread.
uint8_t m_dataType
The ImageStreamIO type code.
int loadConfig(mx::app::appConfigurator &config)
load the configuration system results
bool m_getExistingFirst
If set to true by derivedT, any existing image will be grabbed and sent to processImage before waitin...
virtual void setupConfig()
pcf::IndiProperty m_indiP_imageValid
int startAcquisition()
Implementation of the framegrabber startAcquisition interface.
dev::telemeter< shmimIntegrator > telemeterT
std::mutex m_darkMutex
Pointer to a function to extract the image data as our desired type realT.
pcf::IndiProperty m_indiP_nAverage
dev::frameGrabber< shmimIntegrator > frameGrabberT
int allocate(const dev::shmimT &dummy)
realT(* pixget)(void *, size_t)
INDI_SETCALLBACK_DECL(shmimIntegrator, m_indiP_fpsSource)
float fps()
Implementation of the framegrabber fps interface.
INDI_NEWCALLBACK_DECL(shmimIntegrator, m_indiP_nAverage)
int recordTelem(const telem_fgtimings *)
mx::improc::eigenCube< realT > m_accumImages
Cube used to accumulate images.
INDI_NEWCALLBACK_DECL(shmimIntegrator, m_indiP_avgTime)
float realT
Floating point type in which to do all calculations.
virtual void loadConfig()
friend class shmimIntegrator_test
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
pcf::IndiProperty m_indiP_stateSource
std::string m_fileSaveDir
bool m_stateStringChanged
pcf::IndiProperty m_indiP_nUpdate
pcf::IndiProperty m_indiP_startAveraging
int reconfig()
Implementation of the framegrabber reconfig interface.
shmimIntegrator()
Pointer to a function to extract the image data as our desired type realT.
pcf::IndiProperty m_indiP_fps
this integrator's FPS
dev::shmimMonitor< shmimIntegrator, dark2ShmimT > dark2MonitorT
realT(* dark_pixget)(void *, size_t)
float m_fps
Current FPS from the FPS source.
bool m_continuous
Set to false in configuration to have this run once then stop until triggered.
unsigned m_nUpdate
The rate at which to update the average. If 0 < m_nUpdate < m_nAverage then this is a moving averager...
int acquireAndCheckValid()
Implementation of the framegrabber acquireAndCheckValid interface.
INDI_SETCALLBACK_DECL(shmimIntegrator, m_indiP_stateSource)
bool m_running
Set to false in configuration to have it not start averaging until triggered.
pcf::IndiProperty m_indiP_avgTime
pcf::IndiProperty m_indiP_fpsSource
bool m_stateStringValidOnStart
mx::improc::eigenImage< realT > m_dark2Image
Pointer to a function to extract the image data as our desired type realT.
int loadImageIntoStream(void *dest)
Implementation of the framegrabber loadImageIntoStream interface.
realT(* dark2_pixget)(void *, size_t)
int processImage(void *curr_src, const dev::shmimT &dummy)
virtual int appStartup()
Startup function.
sem_t m_smSemaphore
Semaphore used to synchronize the fg thread and the sm thread.
unsigned m_nAverageDefault
The number of frames to average. Default 10.
std::string m_stateString
dev::shmimMonitor< shmimIntegrator > shmimMonitorT
std::string m_stateSource
The source of the state string used for file management.
virtual int appShutdown()
Shutdown the app.
virtual int appLogic()
Implementation of the FSM for shmimIntegrator.
INDI_NEWCALLBACK_DECL(shmimIntegrator, m_indiP_nUpdate)
float m_avgTime
If non zero, then m_nAverage adjusts automatically to keep a constant averaging time [sec]....
INDI_NEWCALLBACK_DECL(shmimIntegrator, m_indiP_startAveraging)
~shmimIntegrator() noexcept
D'tor, declared and defined for noexcept.
int configureAcquisition()
Implementation of the framegrabber configureAcquisition interface.
mx::improc::eigenImage< realT > m_darkImage
std::string m_fpsSource
Device name for getting fps if time-based averaging is used. This device should have *....
dev::shmimMonitor< shmimIntegrator, darkShmimT > darkMonitorT
bool m_fileSaver
Set to true in configuration to have this save and reload files automatically.
static constexpr bool c_frameGrabber_flippable
app:dev config to tell framegrabber these images can not be flipped
mx::improc::eigenImage< realT > m_avgImage
The average image.
#define INDI_NEWCALLBACK_DEFN(class, prop)
Define the callback for a new property request.
#define INDI_NEWCALLBACK(prop)
Get the name of the static callback wrapper for a new property.
#define INDI_SETCALLBACK_DEFN(class, prop)
Define the callback for a set property request.
#define REG_INDI_SETPROP(prop, devName, propName)
Register a SET INDI property with the class, using the standard callback name.
#define CREATE_REG_INDI_RO_NUMBER(prop, name, label, group)
Create and register a RO INDI property as a number, using the standard callback name.
@ OPERATING
The device is operating, other than homing.
@ READY
The device is ready for operation, but is not operating.
const pcf::IndiProperty & ipRecv
updateIfChanged(m_indiP_angle, "target", m_angle)
std::unique_lock< std::mutex > lock(m_indiMutex)
static constexpr logPrioT LOG_NOTICE
A normal but significant condition.
static constexpr logPrioT LOG_WARNING
A condition has occurred which may become an error, but the process continues.
static std::string indiPrefix()
static std::string configSection()
static std::string configSection()
static std::string indiPrefix()
A device base class which saves telemetry.
int appShutdown()
Perform telemeter application shutdown.
int loadConfig(appConfigurator &config)
Load the device section from an application configurator.
int appLogic()
Perform telemeter application logic.
int setupConfig(appConfigurator &config)
Setup an application configurator for the device section.
int appStartup()
Starts the telemetry log thread.
int checkRecordTimes(const telT &tel, telTs... tels)
Check the time of the last record for each telemetry type and make an entry if needed.
Log entry recording framegrabber timings.