10 #include "../../libMagAOX/libMagAOX.hpp"
11 #include "../../magaox_git_version.h"
13 #include <mx/math/fit/fitGaussian.hpp>
14 #include <mx/improc/imageFilters.hpp>
58 pcf::IndiProperty *
m_prop {
nullptr};
66 throw std::runtime_error(
"attempt to access nullptr prop");
74 m_prop =
new pcf::IndiProperty;
79 pcf::IndiProperty * mp =
m_prop;
130 mx::improc::eigenImage<float>
m_sm;
169 mx::math::fit::fitGaussian2Dsym<float>
m_gfit;
184 mx::app::appConfigurator &_config );
208 int allocate( const dev::shmimT & );
210 int processImage(
void *curr_src, const dev::shmimT & );
284 "Device name for getting fps if time-based averaging is used. This device should have *.fps.current." );
285 config.add(
"fitter.max_loops",
293 "Setting the number of stars to detect in processImage function." );
294 config.add(
"fitter.zero_area",
302 "Setting the pixel area to zero out after detecting stars in processImage function." );
303 config.add(
"fitter.threshold",
311 "setting how many sigma away from the mean you want to classify a detection." );
312 config.add(
"fitter.fwhm_threshold",
314 "fitter.fwhm_threshold",
320 "minumum fwhm to consider something a star." );
321 config.add(
"acquisition.x_center",
323 "acquisition.x_center",
329 "X value for 'center' of image." );
330 config.add(
"acquisition.y_center",
332 "acquisition.y_center",
338 "Y value for 'center' of image." );
351 "fitter.fwhm_threshold" );
353 _config(
m_x_center,
"acquisition.x_center" );
354 _config(
m_y_center,
"acquisition.y_center" );
452 static_cast<void>( dummy );
468 return sqrt( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) );
474 static_cast<void>( dummy );
482 m_image.data()[nn] = ( (uint16_t *)curr_src )[nn] -
m_dark.data()[nn];
489 m_image.data()[nn] = ( (uint16_t *)curr_src )[nn];
501 max =
m_image.maxCoeff( &x, &y );
513 eigenImage<float> llcorn =
m_image.block( 0, 0, 32, 32 );
514 float mean = llcorn.mean();
515 float variance = ( llcorn.array() - mean ).square().sum() / ( llcorn.size() );
516 float stddev = std::sqrt( variance );
517 float z_score = ( max - mean ) / stddev;
524 N_loops = N_loops + 1;
544 eigenImage<float> subImage =
m_image.block(
549 m_gfit.setArray( subImage.data(), subImage.rows(), subImage.cols() );
560 int x_value =
static_cast<int>(
562 int y_value =
static_cast<int>(
m_y );
574 std::string starPrefix =
"star_" + std::to_string( index );
609 max =
m_image.maxCoeff( &x, &y );
610 z_score = ( max - mean ) / stddev;
619 N_loops = N_loops + 1;
639 eigenImage<float> subImage =
m_image.block(
645 m_gfit.setArray( subImage.data(), subImage.rows(), subImage.cols() );
653 int x_value =
static_cast<int>(
655 int y_value =
static_cast<int>(
m_y );
682 int threshold_distance = 20;
689 if( dist < threshold_distance )
695 star.seeing = seeing;
711 std::string starPrefix =
"star_" + std::to_string( index );
724 max =
m_image.maxCoeff( &x, &y );
725 z_score = ( max - mean ) / stddev;
733 double plate_scale = .0795336;
748 std::cout <<
"delta_x = " << delta_x <<
" delta_y = " << delta_y << std::endl;
751 double x_arcsec = -1*delta_y * plate_scale;
752 double y_arcsec = -1*delta_x * plate_scale;
753 std::cout <<
"x_arcsec=" << x_arcsec <<
" y_arcsec=" << y_arcsec << std::endl;
756 pcf::IndiProperty ip( pcf::IndiProperty::Number );
758 ip.setDevice(
"tcsi" );
759 ip.setName(
"pyrNudge" );
761 ip.add( pcf::IndiElement(
"y" ) );
763 ip.add( pcf::IndiElement(
"x" ) );
777 static_cast<void>( dummy );
794 static_cast<void>( dummy );
800 m_dark.data()[nn] += ( (
float *)curr_src )[nn];
817 log<software_error>({__FILE__, __LINE__,
"failed to erase " +
m_detectedStars[n].prop().createUniqueKey()});
828 if(!
ipRecv.find(
"request"))
return 0;
831 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On)
838 else if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::Off)
843 log<software_error>({__FILE__,__LINE__,
"switch state fall through."});
851 if(!
ipRecv.find(
"request"))
return 0;
854 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On)
859 else if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::Off)
864 log<software_error>({__FILE__,__LINE__,
"switch state fall through."});
873 log<software_error>( { __FILE__, __LINE__,
"wrong INDI property received." } );
881 log<software_error>( { __FILE__, __LINE__ } );
895 log<software_error>( { __FILE__, __LINE__,
"Invalid INDI property." } );
899 if(
ipRecv.find(
"current" ) !=
true )
#define IMAGESTRUCT_FLOAT
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.
std::unordered_map< std::string, indiCallBack > m_indiNewCallBacks
Map to hold the NewProperty indiCallBacks for this App, with fast lookup by property name.
indiDriver< MagAOXApp > * m_indiDriver
The INDI driver wrapper. Constructed and initialized by execute, which starts and stops communication...
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
int createROIndiNumber(pcf::IndiProperty &prop, const std::string &propName, const std::string &propLabel="", const std::string &propGroup="")
Create a ReadOnly INDI Number property.
int registerIndiPropertyReadOnly(pcf::IndiProperty &prop)
Register an INDI property which is read only.
std::mutex m_indiMutex
Mutex for locking INDI communications.
int sendNewProperty(const pcf::IndiProperty &ipSend, const std::string &el, const T &newVal)
Send a newProperty command to another device (using the INDI Client interface)
int indiTargetUpdate(pcf::IndiProperty &localProperty, T &localTarget, const pcf::IndiProperty &remoteProperty, bool setBusy=true)
Get the target element value from an new property.
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.
bool m_restart
Flag indicating tha the shared memory should be reinitialized.
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...
mx::improc::eigenImage< float > m_sm
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
virtual void loadConfig()
INDI_SETCALLBACK_DECL(psfAcq, m_indiP_fpsSource)
mx::improc::eigenImage< float > m_image
dev::shmimMonitor< psfAcq, darkShmimT > darkShmimMonitorT
int processImage(void *curr_src, const dev::shmimT &)
pcf::IndiProperty m_indiP_num_stars
float realT
Floating point type in which to do all calculations.
virtual int appLogic()
Implementation of the FSM for psfAcq.
std::vector< float > m_first_x_vals
int recordTelem(const telem_fgtimings *)
uint16_t m_fitCircBuffMaxLength
Maximum length of the latency measurement circular buffers.
virtual int appStartup()
Startup function.
~psfAcq() noexcept
D'tor, declared and defined for noexcept.
mx::improc::eigenImage< float > m_dark
pcf::IndiProperty m_indiP_seeing
INDI_NEWCALLBACK_DECL(psfAcq, m_indiP_acquire_star)
virtual void setupConfig()
int allocate(const dev::shmimT &)
pcf::IndiProperty m_indiP_calcSeeing
virtual int appShutdown()
Shutdown the app.
mx::math::fit::fitGaussian2Dsym< float > m_gfit
dev::shmimMonitor< psfAcq > shmimMonitorT
float m_fitCircBuffMaxTime
Maximum time of the latency meaurement circular buffers.
pcf::IndiProperty m_indiP_fpsSource
std::vector< float > m_first_y_vals
pcf::IndiProperty m_indiP_acquire_star
std::vector< Star > m_detectedStars
pcf::IndiProperty m_indiP_restartAcq
#define INDI_NEWCALLBACK(prop)
Get the name of the static callback wrapper for a new property.
#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.
@ OPERATING
The device is operating, other than homing.
INDI_VALIDATE_CALLBACK_PROPS(function, ipRecv)
float calculateDistance(float x1, float y1, float x2, float y2)
const pcf::IndiProperty & ipRecv
INDI_SETCALLBACK_DEFN(adcTracker, m_indiP_teldata)(const pcf
INDI_NEWCALLBACK_DEFN(acesxeCtrl, m_indiP_windspeed)(const pcf
std::unique_lock< std::mutex > lock(m_indiMutex)
constexpr static logPrioT LOG_INFO
Informational. The info log level is the lowest level recorded during normal operations.
constexpr static logPrioT LOG_NOTICE
A normal but significant condition.
pcf::IndiProperty * m_prop
pcf::IndiProperty & prop()
static std::string configSection()
static std::string indiPrefix()
Log entry recording framegrabber timings.