RTC Toolkit  2.0.0
computation.hpp
Go to the documentation of this file.
1 
12 #ifndef RTCTK_EXAMPLEDATATASK_COMPUTATION_HPP
13 #define RTCTK_EXAMPLEDATATASK_COMPUTATION_HPP
14 
19 
20 #include <chrono>
21 #include <numeric>
22 #include <string>
23 #include <vector>
24 // #include <cblas.h>
25 
26 namespace rtctk::exampleDataTask {
27 
28 using namespace rtctk::componentFramework;
29 
30 class Computation {
31 public:
33 
35  m_last_sample_id = 0;
36  m_sample_idx = 0;
37  m_iteration_idx = 0;
38  }
39 
40  void SetStaticConfig(unsigned to_read, unsigned n_slopes, unsigned n_modes) {
41  // read anything that is unlikely to change.
42  m_n_samples_to_read = to_read;
43  m_n_slopes = n_slopes;
44  m_n_modes = n_modes;
45 
46  // set vectors and matrix to correct size.
47  m_samples.resize(m_n_samples_to_read);
48  m_avg_slopes.resize(m_n_slopes);
49  m_s2m_matrix.resize(m_n_modes, m_n_slopes);
50  m_avg_modes.resize(m_n_modes);
51 
52  // fill with zeros where needed.
53  std::fill(m_avg_slopes.begin(), m_avg_slopes.end(), 0.0);
54  std::fill(m_avg_modes.begin(), m_avg_modes.end(), 0.0);
55 
56  // some simple debug output
57  LOG4CPLUS_DEBUG(GetLogger(), "m_n_slopes: " << m_n_slopes);
58  LOG4CPLUS_DEBUG(GetLogger(), "m_n_modes: " << m_n_modes);
59  LOG4CPLUS_DEBUG(GetLogger(), "m_n_samples_to_read: " << m_n_samples_to_read);
60  }
61 
63  m_s2m_matrix = std::move(s2m_matrix);
64 
65  if (m_n_modes != m_s2m_matrix.GetNrows() || m_n_slopes != m_s2m_matrix.GetNcols()) {
66  std::stringstream err_text;
67  err_text << "s2m wrong shape: ";
68  err_text << " "
69  << "expected : " << m_n_modes << " x " << m_n_slopes;
70  err_text << " "
71  << "received : " << m_s2m_matrix.GetNrows() << " x "
72  << m_s2m_matrix.GetNcols();
74  CII_THROW(RtctkException, err_text.str());
75  }
76  }
77 
78  void Reset() {
79  // This is invoked to clean up in case of stopped during buffering of data.
80  m_last_sample_id = 0;
81  m_sample_idx = 0;
82  m_iteration_idx = 0;
83  }
84 
85  void OnDataAvailable(TopicType const& sample) {
86  m_last_sample_id = sample.sample_id;
87  m_samples[m_sample_idx++] = sample.wfs.slopes;
88  }
89 
90  struct Result {
91  std::vector<float> const& avg_slopes;
92  std::vector<float> const& avg_modes;
93 
94  struct {
95  unsigned last_sample_id;
96  unsigned iteration_idx;
97  std::chrono::duration<double> elapsed;
98  } stats;
99  };
100 
104 
105  if (m_sample_idx != m_n_samples_to_read) {
106  CII_THROW(RtctkException, "not all data available");
107  }
108 
109  LOG4CPLUS_INFO(GetLogger(), "Computation::Compute() - samples: " << m_sample_idx);
110 
111  auto time_start = std::chrono::system_clock::now();
112 
113  ComputeAverageSlopes();
114 
115  ComputeAverageModes();
116 
117  auto elapsed = std::chrono::system_clock::now() - time_start;
118 
119  m_iteration_idx++;
120  m_sample_idx = 0;
121 
122  return {m_avg_slopes, m_avg_modes, m_last_sample_id, m_iteration_idx, elapsed};
123  }
124 
125 private:
126  void ComputeAverageSlopes() {
127  // average matrix to avg_array this is overly simplistic and not optimised
128  for (unsigned i = 0; i < m_n_samples_to_read; i++) {
129  for (unsigned j = 0; j < m_n_slopes; j++) {
130  m_avg_slopes[j] += m_samples[i][j];
131  }
132  }
133 
134  for (unsigned j = 0; j < m_n_slopes; j++) {
135  m_avg_slopes[j] /= static_cast<float>(m_n_samples_to_read);
136  }
137  }
138 
139  void ComputeAverageModes() {
140  // multiply avg_array with S2M matrix to project the average slopes onto modes.
141  // TODO: openblas not available on Centos 7 and no point in making it a dependancy.
142  // for this example I have added a very basic matrix vector multiplication of my own
143  // It is single threaded and not optimised. It is here only for demonstration purposes.
144  // cblas_sgemv(CblasRowMajor, CblasNoTrans, m_n_modes, m_n_slopes, 1.0, m_s2m_matrix.data(),
145  // m_n_slopes, m_avg_slopes.data(), 1, 0.0, m_avg_modes.data(), 1);
146  my_sgemv(
147  m_s2m_matrix.data(), m_avg_slopes.data(), m_avg_modes.data(), m_n_modes, m_n_slopes);
148  }
149 
150  // single threaded sgemv for row major matrix
151  void
152  my_sgemv(const float* mat, const float* in_vec, float* out_vec, uint32_t rows, uint32_t cols) {
153  for (uint32_t i = 0; i < rows; ++i) {
154  out_vec[i] = my_dot_product(mat + i * cols, in_vec, cols);
155  }
156  }
157 
158  // single threaded dot product
159  float my_dot_product(const float* x, const float* y, uint32_t n) {
160  double res = 0.0;
161  for (uint32_t i = 0; i < n; ++i) {
162  res += x[i] * y[i];
163  }
164  return res;
165  }
166 
167  unsigned m_last_sample_id;
168  unsigned m_iteration_idx;
169  unsigned m_sample_idx;
170 
171  unsigned m_n_slopes;
172  unsigned m_n_modes;
173  unsigned m_n_samples_to_read;
174 
175  std::vector<float> m_avg_slopes;
176  std::vector<float> m_avg_modes;
177  std::vector<decltype(decltype(TopicType::wfs)::slopes)> m_samples;
178  MatrixBuffer<float> m_s2m_matrix;
179 };
180 
181 } //namespace rtctk::exampleDataTask
182 
183 #endif // RTCTK_EXAMPLEDATATASK_COMPUTATION_HPP
rtctk::exampleTopic::ScaoLoopTopic::wfs
WfsLoopBaseTopic< N_SUBAPS > wfs
Definition: topics.hpp:30
exceptions.hpp
Provides macros and utilities for exception handling.
rtctk::exampleDataTask::Computation::Result::avg_modes
std::vector< float > const & avg_modes
Definition: computation.hpp:92
rtctk::componentFramework
Definition: commandReplier.cpp:20
matrixBuffer.hpp
Declaration of the MatrixBuffer template class used in APIs.
rtctk::componentFramework::RtctkException
The RtctkException class is the base class for all Rtctk exceptions.
Definition: exceptions.hpp:207
rtctk::exampleDataTask::Computation::Reset
void Reset()
Definition: computation.hpp:78
rtctk::exampleTopic::WfsLoopBaseTopic::slopes
std::array< float, 2 *NSUBAPS > slopes
Definition: topics.hpp:24
rtctk::exampleTopic::ScaoLoopTopic::sample_id
uint64_t sample_id
Definition: topics.hpp:29
rtctk::exampleDataTask::Computation::SetStaticConfig
void SetStaticConfig(unsigned to_read, unsigned n_slopes, unsigned n_modes)
Definition: computation.hpp:40
rtctk::exampleTopic::ScaoLoopTopic
Definition: topics.hpp:28
rtctk::componentFramework::GetLogger
log4cplus::Logger & GetLogger(const std::string &name="")
Get handle to a specific logger (used with logging macros)
rtctkExampleDataTaskGenFitsData.mat
mat
Definition: rtctkExampleDataTaskGenFitsData.py:12
rtctk::exampleDataTask
Definition: businessLogic.hpp:24
rtctk::exampleDataTask::Computation::Computation
Computation()
Definition: computation.hpp:34
rtctkExampleDataTaskGenFitsData.slopes
slopes
Definition: rtctkExampleDataTaskGenFitsData.py:9
rtctk::exampleDataTask::Computation::Result::avg_slopes
std::vector< float > const & avg_slopes
Definition: computation.hpp:91
rtctk::exampleDataTask::Computation::Result
Definition: computation.hpp:52
mudpi::uint32_t
unsigned int uint32_t
Definition: mudpi.h:16
logger.hpp
Logging Support Library based on log4cplus.
rtctk::exampleDataTask::Computation::Compute
Result Compute()
Definition: computation.hpp:101
Computation
Definition: computation.hpp:28
rtctk::exampleDataTask::Computation::Result::iteration_idx
unsigned iteration_idx
Definition: computation.hpp:96
rtctk::exampleDataTask::Computation::OnDataAvailable
void OnDataAvailable(TopicType const &sample)
Definition: computation.hpp:85
rtctk::exampleDataTask::Computation::Result::last_sample_id
unsigned last_sample_id
Definition: computation.hpp:95
rtctk::exampleDataTask::Computation::SetDynamicConfig
void SetDynamicConfig(MatrixBuffer< float > &&s2m_matrix)
Definition: computation.hpp:62
rtctk::componentFramework::MatrixBuffer< float >
topics.hpp
Common topic definitions used in various examples.