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"
329 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.");
330 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.");
332 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.");
334 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.");
336 config.add(
"integrator.continuous",
"",
"integrator.continuous", argType::Required,
"integrator",
"continuous",
false,
"bool",
"Flag controlling whether averaging is continuous or only when triggered. Default true.");
337 config.add(
"integrator.running",
"",
"integrator.running", argType::Required,
"integrator",
"running",
false,
"bool",
"Flag controlling whether averaging is running at startup. Default true.");
339 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.");
340 config.add(
"integrator.fileSaver",
"",
"integrator.fileSaver", argType::Required,
"integrator",
"fileSaver",
false,
"bool",
"Flag controlling whether this saves and reloads files automatically. Default false.");
359 _config(
m_avgTime,
"integrator.avgTime");
360 _config(
m_nUpdate,
"integrator.nUpdate");
364 _config(
m_running,
"integrator.running");
382 createStandardIndiNumber<unsigned>(
m_indiP_nAverage,
"nAverage", 1, std::numeric_limits<unsigned>::max(), 1,
"%u");
388 log<software_error>({__FILE__,__LINE__});
392 createStandardIndiNumber<float>(
m_indiP_avgTime,
"avgTime", 0, std::numeric_limits<float>::max(),0 ,
"%0.1f");
398 log<software_error>({__FILE__,__LINE__});
402 createStandardIndiNumber<unsigned>(
m_indiP_nUpdate,
"nUpdate", 1, std::numeric_limits<unsigned>::max(), 1,
"%u");
408 log<software_error>({__FILE__,__LINE__});
415 log<software_error>({__FILE__,__LINE__});
440 log<software_error>({__FILE__,__LINE__});
449 if( mkdir(
m_fileSaveDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0 )
453 std::stringstream logss;
454 logss <<
"Failed to create image directory (" <<
m_fileSaveDir <<
"). Errno says: " << strerror(errno);
455 log<software_critical>({__FILE__, __LINE__, errno, 0, logss.str()});
465 log<software_critical>({__FILE__, __LINE__, errno,0,
"Initializing S.M. semaphore"});
531 log<software_error>({__FILE__, __LINE__});
536 log<software_error>({__FILE__, __LINE__});
541 log<software_error>({__FILE__, __LINE__});
546 log<software_error>({__FILE__, __LINE__});
560 log<software_error>({__FILE__, __LINE__});
611 static_cast<void>(dummy);
656 log<software_error>({__FILE__, __LINE__,
"bad data type"});
699 static_cast<void>(dummy);
712 data[nn] +=
pixget(curr_src, nn);
740 log<software_critical>({__FILE__, __LINE__, errno, 0,
"Error posting to semaphore"});
763 clock_gettime(CLOCK_REALTIME, &fts);
767 if(gmtime_r(&fts.tv_sec, &uttime) == 0)
770 log<software_alert>({__FILE__,__LINE__,errno,0,
"gmtime_r error. possible loss of timing information."});
773 char cts[] =
"YYYYMMDDHHMMSSNNNNNNNNN";
774 int rv = snprintf(cts,
sizeof(cts),
"%04i%02i%02i%02i%02i%02i%09i", uttime.tm_year+1900,
775 uttime.tm_mon+1, uttime.tm_mday, uttime.tm_hour, uttime.tm_min, uttime.tm_sec,
static_cast<int>(fts.tv_nsec));
777 if(rv !=
sizeof(cts)-1)
780 log<software_alert>({__FILE__,__LINE__, errno, rv,
"did not write enough chars to timestamp"});
785 mx::fits::fitsFile<float> ff;
787 log<text_log>(
"Wrote " + fname);
800 data[nn] =
pixget(curr_src, nn);
844 log<software_critical>({__FILE__, __LINE__, errno, 0,
"Error posting to semaphore"});
857 static_cast<void>(dummy);
868 log<software_error>({__FILE__, __LINE__,
"bad data type"});
892 static_cast<void>(dummy);
910 static_cast<void>(dummy);
921 log<software_error>({__FILE__, __LINE__,
"bad data type"});
945 static_cast<void>(dummy);
967 long N = fnames.size();
968 for(
long n = N-1; n >= 0; --n)
970 std::string fn = mx::ioutils::pathStem(fnames[n]);
975 size_t ed = fn.find(
"__T");
976 if(ed == std::string::npos || ed - st < 2)
continue;
977 std::string stateStr = fn.substr(st,ed-st);
981 mx::fits::fitsFile<float> ff;
1012 log<software_critical>({__FILE__, __LINE__, errno, 0,
"Error posting to semaphore"});
1063 if(clock_gettime(CLOCK_REALTIME, &ts) < 0)
1065 log<software_critical>({__FILE__,__LINE__,errno,0,
"clock_gettime"});
1105 if(
ipRecv.getName() != m_indiP_nAverage.getName())
1107 log<software_error>({__FILE__, __LINE__,
"invalid indi property received"});
1113 if( indiTargetUpdate( m_indiP_nAverage, target,
ipRecv,
true) < 0)
1115 log<software_error>({__FILE__,__LINE__});
1119 m_nAverage = target;
1121 if(m_avgTime > 0 && m_fps > 0)
1123 m_avgTime = m_nAverage/m_fps;
1132 shmimMonitorT::m_restart =
true;
1141 if(
ipRecv.getName() != m_indiP_avgTime.getName())
1143 log<software_error>({__FILE__, __LINE__,
"invalid indi property received"});
1149 if( indiTargetUpdate( m_indiP_avgTime, target,
ipRecv,
true) < 0)
1151 log<software_error>({__FILE__,__LINE__});
1160 shmimMonitorT::m_restart =
true;
1169 if(
ipRecv.getName() != m_indiP_nUpdate.getName())
1171 log<software_error>({__FILE__, __LINE__,
"invalid indi property received"});
1177 if( indiTargetUpdate( m_indiP_nUpdate, target,
ipRecv,
true) < 0)
1179 log<software_error>({__FILE__,__LINE__});
1189 shmimMonitorT::m_restart =
true;
1198 if(
ipRecv.getName() != m_indiP_startAveraging.getName())
1200 log<software_error>({__FILE__, __LINE__,
"invalid indi property received"});
1204 if(!
ipRecv.find(
"toggle"))
return 0;
1206 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::Off)
1208 std::unique_lock<std::mutex> lock(m_indiMutex);
1217 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On)
1219 std::unique_lock<std::mutex> lock(m_indiMutex);
1221 if(m_fileSaver && !m_continuous) m_stateStringChanged =
false;
1223 m_stateStringValidOnStart = m_stateStringValid;
1235 if(
ipRecv.getName() != m_indiP_fpsSource.getName())
1237 log<software_error>({__FILE__, __LINE__,
"Invalid INDI property."});
1241 if(
ipRecv.find(
"current") !=
true )
1246 std::lock_guard<std::mutex> guard(m_indiMutex);
1248 realT fps =
ipRecv[
"current"].get<
float>();
1253 std::cout <<
"Got fps: " << m_fps <<
"\n";
1254 shmimMonitorT::m_restart =
true;
1262 if(
ipRecv.getName() != m_indiP_stateSource.getName())
1264 log<software_error>({__FILE__, __LINE__,
"Invalid INDI property."});
1268 if(
ipRecv.find(
"valid") ==
true )
1270 bool stateStringValid;
1271 if(
ipRecv[
"valid"].get<std::string>() ==
"yes") stateStringValid =
true;
1272 else stateStringValid =
false;
1274 if(stateStringValid != m_stateStringValid) m_stateStringChanged =
true;
1276 m_stateStringValid = stateStringValid;
1279 if(
ipRecv.find(
"current") !=
true )
1286 std::lock_guard<std::mutex> guard(m_indiMutex);
1288 std::string ss =
ipRecv[
"current"].get<std::string>();
1290 if(ss != m_stateString)
1293 m_imageValid =
false;
1295 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)
void loadConfig(mx::app::appConfigurator &config)
load the configuration system results
void setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
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 appStartup()
Startup function.
uint32_t m_width
The width of the images in the stream.
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.
void setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
bool m_getExistingFirst
If set to true by derivedT, any existing image will be grabbed and sent to processImage before waitin...
void 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.
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(prop)
Get the name of the static callback wrapper for a new property.
#define REG_INDI_SETPROP(prop, devName, propName)
Register a SET INDI property with the class, using the standard callback name.
@ OPERATING
The device is operating, other than homing.
@ READY
The device is ready for operation, but is not operating.
void updateIfChanged(pcf::IndiProperty &p, const std::string &el, const T &newVal, indiDriverT *indiDriver, pcf::IndiProperty::PropertyStateType newState=pcf::IndiProperty::Ok)
Update the value of the INDI element, but only if it has changed.
void updateSwitchIfChanged(pcf::IndiProperty &p, const std::string &el, const pcf::IndiElement::SwitchStateType &newVal, indiDriverT *indiDriver, pcf::IndiProperty::PropertyStateType newState=pcf::IndiProperty::Ok)
Update the value of the INDI element, but only if it has changed.
const pcf::IndiProperty & ipRecv
INDI_NEWCALLBACK_DEFN(acesxeCtrl, m_indiP_windspeed)(const pcf
INDI_SETCALLBACK_DEFN(MagAOXApp< _useINDI >, m_indiP_powerChannel)(const pcf
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.
static std::string indiPrefix()
static std::string configSection()
static std::string configSection()
static std::string indiPrefix()
A device 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.