API
openLoopPSDs.hpp
Go to the documentation of this file.
1 /** \file openLoopPSDs.hpp
2  * \brief The MagAO-X openLoopPSDs app header file
3  *
4  * \ingroup openLoopPSDs_files
5  */
6 
7 #ifndef openLoopPSDs_hpp
8 #define openLoopPSDs_hpp
9 
10 
11 #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
12 #include "../../magaox_git_version.h"
13 
14 #include <mx/sigproc/circularBuffer.hpp>
15 #include <mx/sigproc/signalWindows.hpp>
16 
17 #include <mx/math/fft/fftwEnvironment.hpp>
18 #include <mx/math/fft/fft.hpp>
19 
20 /** \defgroup openLoopPSDs
21  * \brief An application to calculate rolling PSDs of modal amplitudes
22  *
23  * <a href="../handbook/operating/software/apps/openLoopPSDs.html">Application Documentation</a>
24  *
25  * \ingroup apps
26  *
27  */
28 
29 /** \defgroup openLoopPSDs_files
30  * \ingroup openLoopPSDs
31  */
32 
33 namespace MagAOX
34 {
35 namespace app
36 {
37 
38 /// Class for application to calculate rolling PSDs of modal amplitudes.
39 /**
40  * \ingroup openLoopPSDs
41  */
42 class openLoopPSDs : public MagAOXApp<true>, public dev::shmimMonitor<openLoopPSDs>
43 {
44  friend class dev::shmimMonitor<openLoopPSDs>;
45 
46 public:
47 
48  typedef float realT;
49  typedef std::complex<realT> complexT;
50 
51  /// The base shmimMonitor type
53 
54  /// The amplitude circular buffer type
55  typedef mx::sigproc::circularBufferIndex<float *, unsigned> ampCircBuffT;
56 
57 protected:
58 
59  /** \name Configurable Parameters
60  *@{
61  */
62 
63  std::string m_clPSDSource; ///< Device name for getting the C.L. PSDs. This is used as the shmim name (unless overriden) and this INDI device should have *.fps.current.
64 
65  int m_nPSDHistory {100}; //
66 
67  ///@}
68 
69  int m_nModes; ///< the number of modes to calculate PSDs for.
70 
71  realT m_fps {0};
72  realT m_df {1};
73 
74  std::vector<realT> m_freq;
75 
76  IMAGE * m_olpsdStream {nullptr};
77 
78 public:
79  /// Default c'tor.
80  openLoopPSDs();
81 
82  /// D'tor, declared and defined for noexcept.
83  ~openLoopPSDs() noexcept
84  {}
85 
86  virtual void setupConfig();
87 
88  /// Implementation of loadConfig logic, separated for testing.
89  /** This is called by loadConfig().
90  */
91  int loadConfigImpl( mx::app::appConfigurator & _config /**< [in] an application configuration from which to load values*/);
92 
93  virtual void loadConfig();
94 
95  /// Startup function
96  /**
97  *
98  */
99  virtual int appStartup();
100 
101  /// Implementation of the FSM for openLoopPSDs.
102  /**
103  * \returns 0 on no critical error
104  * \returns -1 on an error requiring shutdown
105  */
106  virtual int appLogic();
107 
108  /// Shutdown the app.
109  /**
110  *
111  */
112  virtual int appShutdown();
113 
114  //shmimMonitor Interface
115 protected:
116 
117  int allocate( const dev::shmimT & dummy /**< [in] tag to differentiate shmimMonitor parents.*/);
118 
120 
121  int processImage( void * curr_src, ///< [in] pointer to start of current frame.
122  const dev::shmimT & dummy ///< [in] tag to differentiate shmimMonitor parents.
123  );
124 
125 
126  //INDI Interface
127 protected:
128 
129  pcf::IndiProperty m_indiP_clPSDSource;
131 
132  pcf::IndiProperty m_indiP_fps;
133 
134 };
135 
136 openLoopPSDs::openLoopPSDs() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
137 {
138 
139  return;
140 }
141 
143 {
145 
146  config.add("psds.clPSDSource", "", "psds.clPSDSource", argType::Required, "psds", "clPSDSource", false, "string", "Device name for getting the C.L. PSDs. This is used as the shmim name (unless overriden) and this INDI device should have *.fps.current.");
147 }
148 
149 int openLoopPSDs::loadConfigImpl( mx::app::appConfigurator & _config )
150 {
151  _config(m_clPSDSource, "psds.clPSDSource");
152 
154  shmimMonitorT::loadConfig(_config);
155 
156 
157  return 0;
158 }
159 
161 {
162  loadConfigImpl(config);
163 }
164 
166 {
167  if(m_clPSDSource != "")
168  {
169  REG_INDI_SETPROP(m_indiP_clPSDSource, m_clPSDSource, std::string("fps"));
170  }
171  else
172  {
173  log<text_log>("must specify psds.clPSDSource\n", logPrio::LOG_ERROR);
174  m_shutdown = 1;
175  return -1;
176  }
177 
178  createROIndiNumber( m_indiP_fps, "fps", "current", "Circular Buffer");
179  m_indiP_fps.add(pcf::IndiElement("current"));
180  m_indiP_fps["current"] = m_fps;
181 
183  {
184  log<software_error>({__FILE__,__LINE__});
185  return -1;
186  }
187 
188  if(shmimMonitorT::appStartup() < 0)
189  {
190  return log<software_error,-1>({__FILE__, __LINE__});
191  }
192 
194 
195  return 0;
196 }
197 
199 {
200  if( shmimMonitorT::appLogic() < 0)
201  {
202  return log<software_error,-1>({__FILE__,__LINE__});
203  }
204 
205  std::unique_lock<std::mutex> lock(m_indiMutex);
206 
207  if(shmimMonitorT::updateINDI() < 0)
208  {
209  log<software_error>({__FILE__, __LINE__});
210  }
211 
212  return 0;
213 }
214 
216 {
218 
219  return 0;
220 }
221 
223 {
224  static_cast<void>(dummy);
225 
226  //Create the shared memory images
227  uint32_t imsize[3];
228 
229  //First the frequency
230  imsize[0] = shmimMonitorT::m_width;
231  imsize[1] = shmimMonitorT::m_height;
232  imsize[2] = 1;
233 
234  if(m_olpsdStream)
235  {
236  ImageStreamIO_destroyIm(m_olpsdStream);
237  free(m_olpsdStream);
238  }
239  m_olpsdStream = (IMAGE *) malloc(sizeof(IMAGE));
240 
241  ImageStreamIO_createIm_gpu(m_olpsdStream, (m_configName + "_olpsds").c_str(), 3, imsize, IMAGESTRUCT_FLOAT, -1, 1, IMAGE_NB_SEMAPHORE, 0, CIRCULAR_BUFFER | ZAXIS_TEMPORAL, 0);
242 
243  return 0;
244 }
245 
246 int openLoopPSDs::processImage( void * curr_src,
247  const dev::shmimT & dummy
248  )
249 {
250  static_cast<void>(dummy);
251 
252  float * src = static_cast<float *>(curr_src);
253 
254  m_olpsdStream->md->write=1;
255 
256  for(uint32_t n = 0; n < shmimMonitorT::m_height; ++n)
257  {
258  for(uint32_t f = 0; f < shmimMonitorT::m_width; ++f)
259  {
260  m_olpsdStream->array.F[n*shmimMonitorT::m_width + f] = src[n*shmimMonitorT::m_width + f]; // <- divide by t.f. here.
261  }
262  }
263 
264  //Set the time of last write
265  clock_gettime(CLOCK_REALTIME, &m_olpsdStream->md->writetime);
266  m_olpsdStream->md->atime = m_olpsdStream->md->writetime;
267 
268  //Update cnt1
269  m_olpsdStream->md->cnt1 = 0;
270 
271  //Update cnt0
272  m_olpsdStream->md->cnt0 = 0;
273 
274  m_olpsdStream->md->write=0;
275  ImageStreamIO_sempost(m_olpsdStream,-1);
276 
277  return 0;
278 }
279 
280 INDI_SETCALLBACK_DEFN(openLoopPSDs, m_indiP_clPSDSource )(const pcf::IndiProperty &ipRecv)
281 {
282  if( ipRecv.getName() != m_indiP_clPSDSource.getName())
283  {
284  log<software_error>({__FILE__, __LINE__, "Invalid INDI property."});
285  return -1;
286  }
287 
288  if( ipRecv.find("current") != true ) //this isn't valid
289  {
290  log<software_error>({__FILE__, __LINE__, "No current property in fps source."});
291  return 0;
292  }
293 
294  std::lock_guard<std::mutex> guard(m_indiMutex);
295 
296  realT fps = ipRecv["current"].get<realT>();
297 
298  if(fps != m_fps)
299  {
300  m_fps = fps;
301  log<text_log>("set fps to " + std::to_string(m_fps), logPrio::LOG_NOTICE);
302  updateIfChanged(m_indiP_fps, "current", m_fps, INDI_IDLE);
303  shmimMonitorT::m_restart = true;
304  }
305 
306  return 0;
307 
308 } //INDI_SETCALLBACK_DEFN(openLoopPSDs, m_indiP_clPSDSource)
309 
310 } //namespace app
311 } //namespace MagAOX
312 
313 #endif //openLoopPSDs_hpp
#define IMAGESTRUCT_FLOAT
Definition: ImageStruct.hpp:22
The base-class for MagAO-X applications.
Definition: MagAOXApp.hpp:75
std::string m_configName
The name of the configuration file (minus .conf).
Definition: MagAOXApp.hpp:88
stateCodes::stateCodeT state()
Get the current state code.
Definition: MagAOXApp.hpp:2082
int m_shutdown
Flag to signal it's time to shutdown. When not 0, the main loop exits.
Definition: MagAOXApp.hpp:102
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
Definition: MagAOXApp.hpp:1590
int createROIndiNumber(pcf::IndiProperty &prop, const std::string &propName, const std::string &propLabel="", const std::string &propGroup="")
Create a ReadOnly INDI Number property.
Definition: MagAOXApp.hpp:2294
int registerIndiPropertyReadOnly(pcf::IndiProperty &prop)
Register an INDI property which is read only.
Definition: MagAOXApp.hpp:2437
std::mutex m_indiMutex
Mutex for locking INDI communications.
Definition: MagAOXApp.hpp:540
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.
std::string m_shmimName
The name of the shared memory image, is used in /tmp/<shmimName>.im.shm. Derived classes should set a...
int appShutdown()
Shuts down the shmimMonitor thread.
void setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
void loadConfig(mx::app::appConfigurator &config)
load the configuration system results
Class for application to calculate rolling PSDs of modal amplitudes.
pcf::IndiProperty m_indiP_clPSDSource
std::string m_clPSDSource
Device name for getting the C.L. PSDs. This is used as the shmim name (unless overriden) and this IND...
dev::shmimMonitor< openLoopPSDs > shmimMonitorT
The base shmimMonitor type.
pcf::IndiProperty m_indiP_fps
int m_nModes
the number of modes to calculate PSDs for.
virtual int appStartup()
Startup function.
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
~openLoopPSDs() noexcept
D'tor, declared and defined for noexcept.
virtual int appShutdown()
Shutdown the app.
std::vector< realT > m_freq
INDI_SETCALLBACK_DECL(openLoopPSDs, m_indiP_clPSDSource)
int allocate(const dev::shmimT &dummy)
int processImage(void *curr_src, const dev::shmimT &dummy)
mx::sigproc::circularBufferIndex< float *, unsigned > ampCircBuffT
The amplitude circular buffer type.
std::complex< realT > complexT
openLoopPSDs()
Default c'tor.
virtual int appLogic()
Implementation of the FSM for openLoopPSDs.
#define REG_INDI_SETPROP(prop, devName, propName)
Register a SET INDI property with the class, using the standard callback name.
Definition: indiMacros.hpp:264
@ OPERATING
The device is operating, other than homing.
Definition: stateCodes.hpp:50
#define INDI_IDLE
Definition: indiUtils.hpp:28
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.
Definition: indiUtils.hpp:95
const pcf::IndiProperty & ipRecv
INDI_SETCALLBACK_DEFN(MagAOXApp< _useINDI >, m_indiP_powerChannel)(const pcf
Definition: MagAOXApp.hpp:3195
Definition: dm.hpp:24
constexpr static logPrioT LOG_ERROR
An error has occured which the software will attempt to correct.
Definition: logPriority.hpp:40
constexpr static logPrioT LOG_NOTICE
A normal but significant condition.
Definition: logPriority.hpp:46
Software ERR log entry.