7#ifndef userGainCtrl_hpp
8#define userGainCtrl_hpp
12#include <mx/improc/eigenCube.hpp>
13#include <mx/improc/eigenImage.hpp>
14#include <mx/ioutils/fits/fitsFile.hpp>
16#include "../../libMagAOX/libMagAOX.hpp"
17#include "../../magaox_git_version.h"
26 int16_t N = 2* (2*b+1 + 1);
28 return (N+1)*(N+1) - 1;
52 std::vector<std::string> & names,
58 double Nblocksd = (sqrt(1.0+Nmodes) - 1)/4.;
59 int Nblocks = Nblocksd;
61 if(Nblocks < Nblocksd)
77 names.push_back(
"Tip");
84 names.push_back(
"Tip");
86 names.push_back(
"Tilt");
93 names.push_back(
"Tip/Tilt");
102 names.push_back(
"Focus");
108 blocks.push_back(Nzern - 3);
109 names.push_back(
"Z " + std::to_string(4)+
"-" + std::to_string(Nzern));
110 tot += blocks.back();
118 for(
size_t n=0; n < blocks.size(); ++n)
123 if(sum != Nmodes && sum != Nzern)
133 while(currb < Nblocks)
144 uint16_t Nthis = NAtThis - tot;
146 if(tot + Nthis > Nmodes)
148 Nthis = Nmodes - tot;
156 blocks.push_back(Nthis);
157 names.push_back(
"Block " + std::to_string(blocks.size()-1));
163 for(
size_t n=0; n < blocks.size(); ++n)
194 return "multcoeffShmim";
199 return "multcoeffShmim";
305 mx::fits::fitsFile<float>
m_ff;
443 const pcf::IndiProperty &
ipRecv
460 const pcf::IndiProperty &
ipRecv
477 const pcf::IndiProperty &
ipRecv
518 config.add(
"loop.number",
"",
"loop.number", argType::Required,
"loop",
"number",
false,
"int",
"The loop number");
519 config.add(
"blocks.splitTT",
"",
"blocks.splitTT", argType::Required,
"blocks",
"splitTT",
false,
"bool",
"If true, the first block is split into two modes.");
520 config.add(
"blocks.nZern",
"",
"blocks.nZern", argType::Required,
"blocks",
"nZern",
false,
"int",
"Number of Zernikes at beginning. T/T and F are split, the rest in their own block.");
522 config.add(
"blocks.individualModes",
"",
"blocks.individualModes", argType::Required,
"blocks",
"individualModes",
false,
"bool",
"make each block a single mode");
763 for(
int n=0;
n < 100; ++
n)
767 std::string
en =
"block";
820 for(
size_t n=0;
n <
Nb; ++
n)
825 std::string
en =
"block";
851 static_cast<void>(
dummy);
870 static_cast<void>(
dummy);
900 bool constant =
true;
990 static_cast<void>(
dummy);
996 mx::sys::milliSleep(100);
1020 static_cast<void>(
dummy);
1050 bool constant =
true;
1125 static_cast<void>(
dummy);
1131 mx::sys::milliSleep(100);
1155 static_cast<void>(
dummy);
1184 bool constant =
true;
1389 if(gain < 0) gain = 0;
1397 mx::sys::milliSleep(5);
1403 " starting from block " + std::to_string(
block0) +
" " + std::to_string(
gain0));
1412 if(!
ipRecv.find(
"request"))
return 0;
1414 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On)
1416 std::unique_lock<std::mutex>
lock(m_indiMutex);
1418 std::cerr <<
"Got zero all\n";
1419 m_gainsTarget.setZero();
1422 updateSwitchIfChanged(m_indiP_zeroAll,
"request", pcf::IndiElement::Off,
INDI_IDLE);
1434 if( indiTargetUpdate( m_indiP_singleModeNo, target,
ipRecv,
true) < 0)
1436 log<software_error>({__FILE__,__LINE__});
1440 setSingleModeNo(target);
1451 if( indiTargetUpdate( m_indiP_singleGain, target,
ipRecv,
true) < 0)
1453 log<software_error>({__FILE__,__LINE__});
1457 setSingleGain(target);
1468 if( indiTargetUpdate( m_indiP_singleMC, target,
ipRecv,
true) < 0)
1470 log<software_error>({__FILE__,__LINE__});
1474 setSingleMC(target);
1485 if( indiTargetUpdate( m_indiP_powerLawIndex, target,
ipRecv,
true) < 0)
1487 log<software_error>({__FILE__,__LINE__});
1491 powerLawIndex(target);
1502 if( indiTargetUpdate( m_indiP_powerLawFloor, target,
ipRecv,
true) < 0)
1504 log<software_error>({__FILE__,__LINE__});
1508 powerLawFloor(target);
1517 if(!
ipRecv.find(
"request"))
return 0;
1519 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On)
1521 std::unique_lock<std::mutex>
lock(m_indiMutex);
1523 std::cerr <<
"Got Power Law\n";
1526 updateSwitchIfChanged(m_indiP_powerLawSet,
"request", pcf::IndiElement::Off,
INDI_IDLE);
1533 const pcf::IndiProperty &
ipRecv
1544 #ifndef XWCTEST_INDI_CALLBACK_VALIDATION
1551 if(
ipRecv.getName().find(
"block") != 0)
1553 #ifndef XWCTEST_INDI_CALLBACK_VALIDATION
1560 if(
ipRecv.getName().find(
"_gain") != 7)
1562 #ifndef XWCTEST_INDI_CALLBACK_VALIDATION
1569 if(
ipRecv.getName().size() != 12)
1571 #ifndef XWCTEST_INDI_CALLBACK_VALIDATION
1578 #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
1582 int n = std::stoi(
ipRecv.getName().substr(5,2));
1587 if(
ipRecv.find(
"current"))
1592 if(
ipRecv.find(
"target"))
1594 target =
ipRecv[
"target"].get<
double>();
1597 if(target == -1) target =
current;
1611 const pcf::IndiProperty &
ipRecv
1622 #ifndef XWCTEST_INDI_CALLBACK_VALIDATION
1629 if(
ipRecv.getName().find(
"block") != 0)
1631 #ifndef XWCTEST_INDI_CALLBACK_VALIDATION
1638 if(
ipRecv.getName().find(
"_multcoeff") != 7)
1640 #ifndef XWCTEST_INDI_CALLBACK_VALIDATION
1647 if(
ipRecv.getName().size() != 17)
1649 #ifndef XWCTEST_INDI_CALLBACK_VALIDATION
1656 #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
1660 int n = std::stoi(
ipRecv.getName().substr(5,2));
1665 if(
ipRecv.find(
"current"))
1670 if(
ipRecv.find(
"target"))
1672 target =
ipRecv[
"target"].get<
double>();
1675 if(target == -1) target =
current;
1689 const pcf::IndiProperty &
ipRecv
1700 #ifndef XWCTEST_INDI_CALLBACK_VALIDATION
1707 if(
ipRecv.getName().find(
"block") != 0)
1709 #ifndef XWCTEST_INDI_CALLBACK_VALIDATION
1716 if(
ipRecv.getName().find(
"_limit") != 7)
1718 #ifndef XWCTEST_INDI_CALLBACK_VALIDATION
1725 if(
ipRecv.getName().size() != 13)
1727 #ifndef XWCTEST_INDI_CALLBACK_VALIDATION
1734 #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
1739 int n = std::stoi(
ipRecv.getName().substr(5,2));
1744 if(
ipRecv.find(
"current"))
1749 if(
ipRecv.find(
"target"))
1751 target =
ipRecv[
"target"].get<
double>();
1754 if(target == -1) target =
current;
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).
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.
int m_shutdown
Flag to signal it's time to shutdown. When not 0, the main loop exits.
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 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.
IMAGE m_imageStream
The ImageStreamIO shared memory buffer.
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
size_t m_typeSize
The size of the type, in bytes. Result of sizeof.
std::vector< std::string > m_modeBlockNames
pcf::IndiProperty m_indiP_zeroAll
INDI_NEWCALLBACK_DECL(userGainCtrl, m_indiP_powerLawFloor)
static int st_newCallBack_blockLimits(void *app, const pcf::IndiProperty &ipRecv)
The static callback function to be registered for block limits.
virtual int appShutdown()
Shutdown the app.
mx::improc::eigenImage< realT > m_mcsTarget
The target gains.
int m_totalNModes
The total number of WFS modes in the calib.
int newCallBack_blockLimits(const pcf::IndiProperty &ipRecv)
Callback to process a NEW block limits.
int recordBlockGains(bool force=false)
std::vector< float > m_modeBlockGains
int setSingleModeNo(int m)
realT(* mc_pixget)(void *, size_t)
void powerLawIndex(float pli)
mx::improc::eigenImage< realT > m_mcsCurrent
Pointer to a function to extract the image data as our desired type realT.
pcf::IndiProperty m_indiP_powerLawFloor
INDI_NEWCALLBACK_DECL(userGainCtrl, m_indiP_singleMC)
INDI_NEWCALLBACK_DECL(userGainCtrl, m_indiP_zeroAll)
static int st_newCallBack_blockGains(void *app, const pcf::IndiProperty &ipRecv)
The static callback function to be registered for block gains.
friend class userGainCtrl_test
dev::telemeter< userGainCtrl > telemeterT
int newCallBack_blockMCs(const pcf::IndiProperty &ipRecv)
Callback to process a NEW block mult. coeff.s.
std::vector< pcf::IndiProperty > m_indiP_blockGains
INDI_NEWCALLBACK_DECL(userGainCtrl, m_indiP_powerLawIndex)
INDI_NEWCALLBACK_DECL(userGainCtrl, m_indiP_singleGain)
static int st_newCallBack_blockMCs(void *app, const pcf::IndiProperty &ipRecv)
The static callback function to be registered for block mult. coeff.s.
~userGainCtrl() noexcept
D'tor, declared and defined for noexcept.
int setBlockLimit(int n, float l)
mx::improc::eigenImage< realT > m_limitsTarget
The target gains.
int allocate(const gainShmimT &dummy)
INDI_NEWCALLBACK_DECL(userGainCtrl, m_indiP_powerLawSet)
std::vector< uint8_t > m_modeBlockGainsConstant
std::vector< uint16_t > m_modeBlockN
std::vector< pcf::IndiProperty > m_indiP_blockMCs
int setBlockMC(int n, float mc)
pcf::IndiProperty m_indiP_modes
void powerLawFloor(float plf)
int setBlockGain(int n, float g)
pcf::IndiProperty m_indiP_singleModeNo
std::vector< uint8_t > m_modeBlockMCsConstant
INDI_NEWCALLBACK_DECL(userGainCtrl, m_indiP_singleModeNo)
std::vector< float > m_modeBlockLims
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
int setSingleGain(float g)
realT(* limit_pixget)(void *, size_t)
dev::shmimMonitor< userGainCtrl, limitShmimT > limitShmimMonitorT
userGainCtrl()
Default c'tor.
realT(* pixget)(void *, size_t)
int processImage(void *curr_src, const gainShmimT &dummy)
pcf::IndiProperty m_indiP_singleMC
float realT
Floating point type in which to do all calculations.
dev::shmimMonitor< userGainCtrl, gainShmimT > shmimMonitorT
pcf::IndiProperty m_indiP_powerLawSet
pcf::IndiProperty m_indiP_powerLawIndex
std::vector< float > m_modeBlockMCs
virtual int appLogic()
Implementation of the FSM for userGainCtrl.
virtual int appStartup()
Startup function.
int recordTelem(const telem_blockgains *)
virtual void loadConfig()
std::vector< pcf::IndiProperty > m_indiP_blockLimits
std::vector< uint8_t > m_modeBlockLimsConstant
int newCallBack_blockGains(const pcf::IndiProperty &ipRecv)
Callback to process a NEW block gain request.
int setSingleMC(float mc)
std::vector< uint16_t > m_modeBlockStart
Pointer to a function to extract the image data as our desired type realT.
std::mutex m_modeBlockMutex
mx::improc::eigenImage< realT > m_gainsCurrent
The current gains.
mx::improc::eigenImage< realT > m_gainsTarget
The target gains.
mx::improc::eigenImage< realT > m_limitsCurrent
Pointer to a function to extract the image data as our desired type realT.
pcf::IndiProperty m_indiP_singleGain
mx::fits::fitsFile< float > m_ff
dev::shmimMonitor< userGainCtrl, multcoeffShmimT > mcShmimMonitorT
virtual void setupConfig()
#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.
@ OPERATING
The device is operating, other than homing.
@ READY
The device is ready for operation, but is not operating.
@ CONNECTED
The application has connected to the device or service.
@ NOTCONNECTED
The application is not connected to the device or service.
#define INDI_VALIDATE_CALLBACK_PROPS(prop1, prop2)
Standard check for matching INDI properties in a callback.
int addNumberElement(pcf::IndiProperty &prop, const std::string &name, const T &min, const T &max, const T &step, const std::string &format, const std::string &label="")
Add a standard INDI Number element.
uint16_t modesAtBlock(uint16_t b)
uint16_t modesInBlock(uint16_t b)
Calculate the number of modes in 1 block.
const pcf::IndiProperty & ipRecv
int blockModes(std::vector< uint16_t > &blocks, std::vector< std::string > &names, uint16_t Nmodes, uint16_t Nzern, bool splitTT)
Calculate the number of blocks and the number of modes per block.
std::unique_lock< std::mutex > lock(m_indiMutex)
static constexpr logPrioT LOG_CRITICAL
The process can not continue and will shut down (fatal)
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.
static std::string configSection()
static std::string indiPrefix()
static std::string indiPrefix()
static std::string configSection()
static std::string indiPrefix()
static std::string configSection()
Log entry recording electronics rack temperature.