7 #ifndef photonCounter_hpp
8 #define photonCounter_hpp
12 #include <mx/improc/eigenCube.hpp>
13 #include <mx/improc/eigenImage.hpp>
14 using namespace mx::improc;
16 #include "../../libMagAOX/libMagAOX.hpp"
17 #include "../../magaox_git_version.h"
46 friend class photonCounter_test;
60 static constexpr
bool c_frameGrabber_flippable =
false;
71 realT (*pixget)(
void *, size_t) {
nullptr};
72 void * m_curr_src {
nullptr};
101 virtual void setupConfig();
106 int loadConfigImpl( mx::app::appConfigurator & _config );
108 virtual void loadConfig();
114 virtual int appStartup();
121 virtual int appLogic();
127 virtual int appShutdown();
131 int processImage(
void * curr_src,
152 int configureAcquisition();
159 int startAcquisition();
166 int acquireAndCheckValid();
173 int loadImageIntoStream(
void * dest );
200 photonCounter::photonCounter() :
MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
211 config.add(
"parameters.quantile",
"",
"parameters.quantile", argType::Required,
"parameters",
"quantile",
false,
"float",
"The quantile of the threshold.");
212 config.add(
"parameters.Nstack",
"",
"parameters.Nstack", argType::Required,
"parameters",
"Nstack",
false,
"string",
"The number of frames to stack.");
213 config.add(
"parameters.Ncalibrate",
"",
"parameters.Ncalibrate", argType::Required,
"parameters",
"Ncalibrate",
false,
"string",
"The number of frames for calibration.");
241 log<software_critical>({__FILE__, __LINE__, errno,0,
"Initializing S.M. semaphore"});
261 createStandardIndiNumber<int>(
m_indiP_calibrateSteps,
"nFrames", 0, 1000000, 1,
"%d",
"The calibration ",
"Calibration control");
264 createStandardIndiNumber<int>(
m_indiP_stackFrames,
"stackNframes", 0, 1000000, 1,
"%d",
"The calibration ",
"Calibration control");
267 createStandardIndiNumber<float>(
m_indiP_quantileCut,
"quantile", 0, 1.0, 0.0001,
"%0.3f",
"The quantile cut",
"Calibration control");
292 log<software_error>({__FILE__, __LINE__});
297 log<software_error>({__FILE__, __LINE__});
320 static_cast<void>(dummy);
353 static_cast<void>(dummy);
361 std::cout <<
"Start data collection" << std::endl;
400 std::vector<float> tempVec;
403 tempVec.push_back(val);
411 std::sort(tempVec.begin(), tempVec.end());
416 std::cout <<
"q0: [" << tempVec[0] <<
", " << tempVec[q_index] <<
", " << tempVec[tempVec.size()-1] <<
"]" << std::endl;
423 std::cout <<
"Calibration done!" << std::endl;
436 float dI = (float)camera_image(row_i, col_i);
455 log<software_critical>({__FILE__, __LINE__, errno, 0,
"Error posting to semaphore"});
499 if(clock_gettime(CLOCK_REALTIME, &ts) < 0)
501 log<software_critical>({__FILE__,__LINE__,errno,0,
"clock_gettime"});
547 if(
ipRecv.getName() != m_indiP_calibrateToggle.getName())
549 log<software_error>({__FILE__, __LINE__,
"invalid indi property received"});
553 if(!
ipRecv.find(
"request"))
return 0;
555 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On)
559 std::cout <<
"Request calibration" << std::endl;
560 m_calibrationSet =
false;
572 if(
ipRecv.getName() != m_indiP_quantileCut.getName()){
573 log<software_error>({__FILE__,__LINE__,
"wrong INDI property received."});
580 if(
ipRecv.find(
"current"))
581 current =
ipRecv[
"current"].get<
float>();
584 target =
ipRecv[
"target"].get<float>();
586 if(target == -1) target = current;
591 std::lock_guard<std::mutex> guard(m_indiMutex);
593 m_quantile_cut = target;
601 if(
ipRecv.getName() != m_indiP_calibrateSteps.getName())
603 log<software_error>({__FILE__,__LINE__,
"wrong INDI property received."});
610 if(
ipRecv.find(
"current"))
612 current =
ipRecv[
"current"].get<
int>();
617 target =
ipRecv[
"target"].get<
int>();
620 if(target == -1) target = current;
627 std::lock_guard<std::mutex> guard(m_indiMutex);
629 calibration_steps = target;
630 m_calibrationCube.resize(m_image_width, m_image_height, calibration_steps);
631 m_calibrationCube.setZero();
640 if(
ipRecv.getName() != m_indiP_stackFrames.getName())
642 log<software_error>({__FILE__,__LINE__,
"wrong INDI property received."});
649 if(
ipRecv.find(
"current"))
651 current =
ipRecv[
"current"].get<
int>();
656 target =
ipRecv[
"target"].get<
int>();
659 if(target == -1) target = current;
666 std::lock_guard<std::mutex> guard(m_indiMutex);
668 m_stack_frames = target;
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.
int createStandardIndiRequestSw(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 request element.
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.
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
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 loadConfig(mx::app::appConfigurator &config)
load the configuration system results
int updateINDI()
Update the INDI properties for this device controller.
uint8_t m_dataType
The ImageStreamIO type code.
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
int loadImageIntoStream(void *dest)
Implementation of the framegrabber loadImageIntoStream interface.
int processImage(void *curr_src, const dev::shmimT &dummy)
~photonCounter() noexcept
D'tor, declared and defined for noexcept.
virtual void setupConfig()
INDI_NEWCALLBACK_DECL(photonCounter, m_indiP_calibrateSteps)
virtual int appStartup()
Startup function.
pcf::IndiProperty m_indiP_calibrateToggle
sem_t m_smSemaphore
Semaphore used to synchronize the fg thread and the sm thread.
INDI_NEWCALLBACK_DECL(photonCounter, m_indiP_calibrateToggle)
virtual int appLogic()
Implementation of the FSM for photonCounter.
virtual void loadConfig()
mx::improc::eigenImage< realT > m_photonCountedImage
pcf::IndiProperty m_indiP_stackFrames
float realT
Floating point type in which to do all calculations.
int acquireAndCheckValid()
Implementation of the framegrabber acquireAndCheckValid interface.
mx::improc::eigenImage< realT > m_thresholdImage
virtual int appShutdown()
Shutdown the app.
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
int configureAcquisition()
Implementation of the framegrabber configureAcquisition interface.
dev::shmimMonitor< photonCounter > shmimMonitorT
int reconfig()
Implementation of the framegrabber reconfig interface.
dev::frameGrabber< photonCounter > frameGrabberT
pcf::IndiProperty m_indiP_calibrateSteps
mx::improc::eigenImage< realT > m_dark_image
INDI_NEWCALLBACK_DECL(photonCounter, m_indiP_stackFrames)
mx::improc::eigenCube< realT > m_calibrationCube
INDI_NEWCALLBACK_DECL(photonCounter, m_indiP_quantileCut)
pcf::IndiProperty m_indiP_quantileCut
uint32_t current_calibration_iteration
int allocate(const dev::shmimT &dummy)
int startAcquisition()
Implementation of the framegrabber startAcquisition interface.
#define INDI_NEWCALLBACK(prop)
Get the name of the static callback wrapper for a new property.
@ OPERATING
The device is operating, other than homing.
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
updateIfChanged(m_indiP_angle, "target", m_angle)
INDI_NEWCALLBACK_DEFN(acesxeCtrl, m_indiP_windspeed)(const pcf
std::unique_lock< std::mutex > lock(m_indiMutex)