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"
192 mx::app::appConfigurator &
_config );
344 config.add(
"integrator.nAverage",
346 "integrator.nAverage",
352 "The default number of frames to average. Default 10. Can be changed via INDI." );
354 "integrator.fpsSource",
356 "integrator.fpsSource",
362 "Device name for getting fps if time-based averaging is used. This device should have *.fps.current." );
364 config.add(
"integrator.avgTime",
366 "integrator.avgTime",
372 "If non zero, then m_nAverage adjusts automatically to keep a constant averaging time [sec]. Default "
373 "0. Can be changed via INDI." );
375 config.add(
"integrator.nUpdate",
377 "integrator.nUpdate",
383 "The rate at which to update the average. If 0 < m_nUpdate < m_nAverage then this is a moving "
384 "averager. Default 0. If 0, then it is a simple average." );
386 config.add(
"integrator.continuous",
388 "integrator.continuous",
394 "Flag controlling whether averaging is continuous or only when triggered. Default true." );
395 config.add(
"integrator.running",
397 "integrator.running",
403 "Flag controlling whether averaging is running at startup. Default true." );
405 config.add(
"integrator.stateSource",
407 "integrator.stateSource",
413 "///< Device name for getting the state string for file management. This device should have "
414 "*.state_string.current." );
415 config.add(
"integrator.fileSaver",
417 "integrator.fileSaver",
423 "Flag controlling whether this saves and reloads files automatically. Default false." );
461 m_indiP_nAverage,
"nAverage", 1, std::numeric_limits<unsigned>::max(), 1,
"%u" );
535 std::stringstream
logss;
692 static_cast<void>(
dummy );
774 static_cast<void>(
dummy );
852 "gmtime_r error. possible loss of timing information." } );
855 char cts[] =
"YYYYMMDDHHMMSSNNNNNNNNN";
858 "%04i%02i%02i%02i%02i%02i%09i",
865 static_cast<int>(
fts.tv_nsec ) );
867 if(
rv !=
sizeof(
cts ) - 1 )
877 mx::fits::fitsFile<float>
ff;
948 static_cast<void>(
dummy );
979 static_cast<void>(
dummy );
996 static_cast<void>(
dummy );
1027 static_cast<void>(
dummy );
1049 for(
long n =
N - 1;
n >= 0; --
n )
1051 std::string
fn = mx::ioutils::pathStem(
fnames[
n] );
1057 size_t ed =
fn.find(
"__T" );
1058 if(
ed == std::string::npos ||
ed -
st < 2 )
1064 mx::fits::fitsFile<float>
ff;
1190 if(
ipRecv.getName() != m_indiP_nAverage.getName() )
1192 log<software_error>( { __FILE__, __LINE__,
"invalid indi property received" } );
1198 if( indiTargetUpdate( m_indiP_nAverage, target,
ipRecv,
true ) < 0 )
1200 log<software_error>( { __FILE__, __LINE__ } );
1204 m_nAverage = target;
1206 if( m_avgTime > 0 && m_fps > 0 )
1208 m_avgTime = m_nAverage / m_fps;
1217 shmimMonitorT::m_restart =
true;
1226 if(
ipRecv.getName() != m_indiP_avgTime.getName() )
1228 log<software_error>( { __FILE__, __LINE__,
"invalid indi property received" } );
1234 if( indiTargetUpdate( m_indiP_avgTime, target,
ipRecv,
true ) < 0 )
1236 log<software_error>( { __FILE__, __LINE__ } );
1245 shmimMonitorT::m_restart =
true;
1254 if(
ipRecv.getName() != m_indiP_nUpdate.getName() )
1256 log<software_error>( { __FILE__, __LINE__,
"invalid indi property received" } );
1262 if( indiTargetUpdate( m_indiP_nUpdate, target,
ipRecv,
true ) < 0 )
1264 log<software_error>( { __FILE__, __LINE__ } );
1273 shmimMonitorT::m_restart =
true;
1282 if(
ipRecv.getName() != m_indiP_startAveraging.getName() )
1284 log<software_error>( { __FILE__, __LINE__,
"invalid indi property received" } );
1288 if( !
ipRecv.find(
"toggle" ) )
1291 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::Off )
1293 std::unique_lock<std::mutex>
lock( m_indiMutex );
1299 updateSwitchIfChanged( m_indiP_startAveraging,
"toggle", pcf::IndiElement::Off,
INDI_IDLE );
1302 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On )
1304 std::unique_lock<std::mutex>
lock( m_indiMutex );
1306 if( m_fileSaver && !m_continuous )
1307 m_stateStringChanged =
false;
1309 m_stateStringValidOnStart = m_stateStringValid;
1314 updateSwitchIfChanged( m_indiP_startAveraging,
"toggle", pcf::IndiElement::On,
INDI_BUSY );
1321 if(
ipRecv.getName() != m_indiP_fpsSource.getName() )
1323 log<software_error>( { __FILE__, __LINE__,
"Invalid INDI property." } );
1327 if(
ipRecv.find(
"current" ) !=
true )
1332 std::lock_guard<std::mutex> guard( m_indiMutex );
1334 realT fps =
ipRecv[
"current"].get<
float>();
1339 std::cout <<
"Got fps: " << m_fps <<
"\n";
1340 shmimMonitorT::m_restart =
true;
1341 frameGrabberT::m_reconfig =
true;
1349 if(
ipRecv.getName() != m_indiP_stateSource.getName() )
1351 log<software_error>( { __FILE__, __LINE__,
"Invalid INDI property." } );
1355 if(
ipRecv.find(
"valid" ) ==
true )
1357 bool stateStringValid;
1358 if(
ipRecv[
"valid"].get<std::string>() ==
"yes" )
1359 stateStringValid =
true;
1361 stateStringValid =
false;
1363 if( stateStringValid != m_stateStringValid )
1364 m_stateStringChanged =
true;
1366 m_stateStringValid = stateStringValid;
1369 if(
ipRecv.find(
"current" ) !=
true )
1374 std::lock_guard<std::mutex> guard( m_indiMutex );
1376 std::string ss =
ipRecv[
"current"].get<std::string>();
1378 if( ss != m_stateString )
1381 m_imageValid =
false;
1383 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
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.
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)
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
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.