mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
directPhaseReconstructor.hpp
1 #ifndef directPhaseReconstructor_hpp
2 #define directPhaseReconstructor_hpp
3 
4 
5 #include "../../improc/eigenImage.hpp"
6 #include "../../improc/eigenCube.hpp"
7 #include "../../ioutils/fits/fitsFile.hpp"
8 using namespace mx::improc;
9 using namespace mx::fits;
10 
11 #include "../../math/cuda/cudaPtr.hpp"
12 #include "../../math/cuda/templateCublas.hpp"
13 
14 #include "../../sigproc/signalWindows.hpp"
15 
16 #ifdef DEBUG
17 #define BREAD_CRUMB std::cout << "DEBUG: " << __FILE__ << " " << __LINE__ << "\n";
18 #else
19 #define BREAD_CRUMB
20 #endif
21 
22 namespace mx
23 {
24 namespace AO
25 {
26 namespace sim
27 {
28 
29 
30 struct directPhaseReconstructorSpec
31 {
32  std::string dmName;
33  std::string basisName;
34 
35  std::string rMatId;
36 };
37 
38 /// Direct Phase Reconstructor
39 /** Calculates modal amplitudes by direct projection of modes onto the phase screen.
40  */
41 template<typename realT>
43 {
44 public:
45 
46  ///The type of the WFS image
47  typedef Eigen::Array<realT, -1, -1> imageT;
48 
49  ///The type of the response matrix
50  typedef Eigen::Array<realT, -1, -1> rmatT;
51 
52  ///The specificaion type.
53  typedef directPhaseReconstructorSpec specT;
54 
55 protected:
56 
57  /** \name The Pupil
58  * @{
59  */
60  imageT * m_pupil {nullptr};
61  int m_nPix {0};
62  ///@}
63 
64  /** \name The Basis
65  * @{
66  */
67  improc::eigenCube<realT> *m_modes {nullptr}; ///< The mirror modes, managed by the DM
68 
69  int m_nModes {0}; ///<The number of modes to be reconstructed
70 
71  int m_detRows {0}; ///<The size of the WFS image, in rows
72  int m_detCols {0};///<The size of the WFS image, in columns
73  ///@}
74 
75  /** \name The Reconstructor
76  * @{
77  */
78 
79  #ifdef MXAO_USE_GPU
80  cublasHandle_t *m_cublasHandle;
81 
83  cuda::cudaPtr<realT> m_zero;
84 
85  cuda::cudaPtr<realT> m_devRecon;
86  cuda::cudaPtr<realT> m_devSlopes;
87  cuda::cudaPtr<realT> m_devAmps;
88 
89  #else
90  Eigen::Array<realT,-1,-1> m_recon; ///< The reconstructor matrix.
91  #endif
92 
93  int m_measurementSize {0}; ///<The number of values in the measurement
94  std::vector<size_t> * m_idx {nullptr}; /// The offset coordinates of non-zero pixels in the pupil. Set by the DM.
95  ///@}
96 
97  realT m_calAmp {1e-6}; ///<The calibration amplitude used for response matrix acquisition
98 
99  imageT m_rMat; ///<The response matrix
100 
101  eigenCube<realT> m_rImages;
102 
103 
104 public:
105  ///Default c'tor
107 
108  template<typename AOSysT>
109  void initialize( AOSysT & AOSys,
110  specT & spec
111  );
112 
113 
114  ///Get the calibration amplitude used in response matrix acquisition (m_calAmp)
115  realT calAmp();
116 
117 
118  ///Set the calibration amplitude used in response matrix acquisition (m_calAmp)
119  /**
120  * \param ca [in] the new calibration amplitude
121  */
122  void calAmp(realT ca);
123 
124  ///Get the number of modes (m_nModes)
125  int nModes();
126 
127  ///Get the number of detector rows (m_detRows)
128  int detRows();
129 
130  ///Set the number of detector rows (m_detRows)
131  void detRows(int dr);
132 
133  ///Get the number of detector columns (m_detCols)
134  int detCols();
135 
136  ///Set the number of detector columns (m_detCols)
137  void detCols(int dc);
138 
139  ///Load the reconstrutor from the specified FITS file
140  /**
141  * \param fname is the name of the FITS file, including path
142  */
143  void loadRecon(const std::string & fname);
144 
145  ///Return the size of the unbinned measurement
146  int measurementSize();
147 
148 
149  ///Calculate the slope measurement
150  /**
151  * \param slopes [out] a (m_measurementSize X 2) array of slopes
152  * \param wfsImage [in] the WFS image from which to measure the slopes
153  */
154  template<typename measurementT, typename wfsImageT>
155  void calcMeasurement(measurementT & slopes, wfsImageT & wfsImage);
156 
157  ///Reconstruct the wavefront from the input image, producing the modal amplitude vector
158  template<typename measurementT, typename wfsImageT>
159  void reconstruct(measurementT & commandVect, wfsImageT & wfsImage);
160 
161  ///Initialize the response matrix for acquisition
162  /**
163  * \param nmodes the number of modes
164  * \param calamp the calibration amplitude
165  * \param detrows the number of detector rows
166  * \param detcols the number of detector columns
167  */
168  void initializeRMat(int nmodes, realT calamp, int detrows,int detcols);
169 
170  ///Accumalte the next measurement in the response matrix
171  /**
172  * \param i the measurement index
173  * \param measureVec is the i-th measurement vector
174  */
175  template<typename measurementT>
176  void accumulateRMat(int i, measurementT &measureVec);
177 
178 
179  template<typename measurementT, typename wfsImageT>
180  void accumulateRMat(int i, measurementT &measureVec, wfsImageT & wfsImage);
181 
182  ///Write the accumulated response matrix to disk
183  /**
184  * \param fname the name, including path, of the response matrix
185  */
186  void saveRMat(std::string fname);
187 
188  void saveRImages(std::string fname);
189 };
190 
191 
192 template<typename realT>
194 {
195 }
196 
197 template<typename realT>
198 template<typename AOSysT>
199 void directPhaseReconstructor<realT>::initialize( AOSysT & AOSys,
200  specT & spec
201  )
202 {
203  static_cast<void>(spec);
204 
205 
206  m_pupil = &AOSys._pupil;
207 
208  m_nPix = m_pupil->sum();
209 
210  m_modes = &AOSys.dm.m_infF;
211 
212  m_nModes = m_modes->planes();
213  m_detRows = m_modes->rows();
214  m_detCols = m_modes->cols();
215 
216  m_idx = &AOSys.dm.m_idx;
217 
218  m_measurementSize = m_idx->size();
219 
220  #ifdef MXAO_USE_GPU
221 
222  m_cublasHandle = &AOSys.m_cublasHandle;
223  //m_cublasHandle = new cublasHandle_t; //&AOSys.m_cublasHandle;
224  //cublasCreate(m_cublasHandle);
225  //cublasSetPointerMode(*m_cublasHandle, CUBLAS_POINTER_MODE_DEVICE);
226 
227 
228  m_one.resize(1);
229  realT one = 1.0;
230  m_one.upload(&one, 1);
231 
232  m_zero.resize(1);
233  m_zero.initialize();
234 
235  imageT recon;
236  recon.resize(m_nModes, m_measurementSize);
237  for(int pp=0; pp<m_nModes; ++pp)
238  {
239  for(int nn=0; nn < m_idx->size(); ++nn)
240  {
241  recon(pp,nn) = *(m_modes->image(pp).data() + (*m_idx)[nn])/m_nPix;
242  }
243  }
244 
245  m_devRecon.upload(recon.data(), recon.rows()*recon.cols());
246 
247  m_devSlopes.resize(m_measurementSize);
248 
249  m_devAmps.resize(m_nModes);
250 
251  #else
252 
253  m_recon.resize(m_measurementSize, m_nModes);
254 
255  for(int pp=0; pp<m_nModes; ++pp)
256  {
257  for(int nn=0; nn < m_idx->size(); ++nn)
258  {
259  m_recon(nn,pp) = *(m_modes->image(pp).data() + (*m_idx)[nn])/m_nPix;
260  }
261  }
262 
263  #endif
264 
265 
266 }
267 
268 
269 
270 template<typename realT>
272 {
273  return 0.5*800.0e-9/math::two_pi<realT>();
274 }
275 
276 template<typename realT>
278 {
279  return;
280 }
281 
282 template<typename realT>
284 {
285  return m_nModes;
286 }
287 
288 template<typename realT>
290 {
291  return m_detRows;
292 }
293 
294 template<typename realT>
296 {
297  return m_detCols;
298 }
299 
300 template<typename realT>
301 void directPhaseReconstructor<realT>::loadRecon(const std::string & fname)
302 {
303 #if 0
304  fitsFile<realT> ff;
305  fitsHeader head;
306 
307  ff.read(m_recon, head, fname);
308 #endif
309 
310 }
311 
312 template<typename realT>
314 {
315  return m_measurementSize;
316 }
317 
318 template<typename realT>
319 template<typename measurementT, typename wfsImageT>
320 void directPhaseReconstructor<realT>::calcMeasurement(measurementT & slopes, wfsImageT & wfsImage)
321 {
322  slopes.measurement.resize(m_measurementSize);
323 
324  realT * imp = wfsImage.image.data();
325  for(int nn=0; nn < m_idx->size(); ++nn)
326  {
327  slopes.measurement[nn] = *(imp + (*m_idx)[nn]);
328  }
329 
330 }
331 
332 template<typename realT>
333 template<typename measurementT, typename wfsImageT>
334 void directPhaseReconstructor<realT>::reconstruct(measurementT & commandVect, wfsImageT & wfsImage)
335 {
336 
337  #ifdef MXAO_USE_GPU
338 
339  static measurementT slopes; //static to prevent re-alloc
340 
341  calcMeasurement(slopes, wfsImage);
342 
343  m_devSlopes.upload(slopes.measurement.data(), slopes.measurement.size());
344 
345  //realT alpha = 1.;
346  //realT zero = 0;
347 
348  cublasStatus_t stat = cuda::cublasTgemv<realT>(*m_cublasHandle, CUBLAS_OP_N, m_nModes, m_measurementSize, m_one(), m_devRecon(), m_devSlopes(), m_zero(), m_devAmps());
349  if(stat != CUBLAS_STATUS_SUCCESS)
350  {
351  std::cerr << "cublas error\n";
352  }
353 
354  commandVect.measurement.resize(m_nModes);
355  m_devAmps.download(commandVect.measurement.data());
356 
357  commandVect.iterNo = wfsImage.iterNo;
358 
359  #else
360 
361  BREAD_CRUMB;
362 
363  /* Only needed if using "slopes" below (keep for debugging):
364  static measurementT slopes;
365  calcMeasurement(slopes, wfsImage);
366  */
367 
368  #pragma omp parallel for
369  for(int j=0; j< m_nModes; ++j)
370  {
371  //The brutest forcest way, slower:
372  //commandVect.measurement[j] = (wfsImage.image*m_modes->image(j)).sum()/ m_nPix;
373 
374  //The fastest non-GPU way:
375  realT amp = 0;
376  for(size_t k=0; k < m_idx->size(); ++k)
377  {
378  amp += *(wfsImage.image.data() + (*m_idx)[k]) *m_recon(k,j);
379  }
380  commandVect.measurement[j] = amp;
381 
382  /* Slightly slower, using the slopes calc (keep for debugging slopes calc):
383  realT amp = 0;
384  for(size_t k=0; k < slopes.measurement.size(); ++k)
385  {
386  amp += slopes.measurement[k]*m_recon(k,j);
387  }
388  commandVect.measurement[j] = amp;
389  */
390 
391 
392  }
393 
394  commandVect.iterNo = wfsImage.iterNo;
395 
396  #endif
397 }
398 
399 template<typename realT>
400 void directPhaseReconstructor<realT>::initializeRMat(int nModes, realT calamp, int detRows, int detCols)
401 {
402  m_nModes = nModes;
403 
404  m_detRows = detRows;
405  m_detCols = detCols;
406 
407  m_rMat.resize(measurementSize(), nModes);
408  m_rMat.setZero();
409 
410  m_rImages.resize(m_detRows, m_detCols, m_nModes);
411 }
412 
413 template<typename realT>
414 template<typename measurementT>
415 void directPhaseReconstructor<realT>::accumulateRMat(int i, measurementT &measureVec)
416 {
417  int l = 0;
418  for(int j=0; j<measureVec.measurement.rows(); ++j)
419  {
420  for(int k=0; k<measureVec.measurement.cols(); ++k)
421  {
422  m_rMat(l, i) = measureVec.measurement(j,k);
423  ++l;
424  }
425  }
426 
427  //m_rMat.col(i) = measureVec.measurement.row(0);
428 }
429 
430 template<typename realT>
431 template<typename measurementT,typename wfsImageT>
432 void directPhaseReconstructor<realT>::accumulateRMat(int i, measurementT &measureVec, wfsImageT & wfsImage)
433 {
434  accumulateRMat(i, measureVec);
435  m_rImages.image(i) = wfsImage.image;
436 }
437 
438 template<typename realT>
440 {
441  fitsFile<realT> ff;
442  fitsHeader head;
443 
444  head.append("DETROWS", m_detRows, "WFS detector rows");
445  head.append("DETCOLS", m_detCols, "WFS detector cols");
446  head.append("CALAMP", m_calAmp, "DM Calibration amplitude");
447  head.append("NMODES", m_nModes, "Number of modes included in the response matrix.");
448 
449  ff.write(fname, m_rMat, head);
450 }
451 
452 template<typename realT>
453 void directPhaseReconstructor<realT>::saveRImages(std::string fname)
454 {
455  fitsFile<realT> ff;
456  fitsHeader head;
457 
458 
459  head.append("DETROWS", m_detRows, "WFS detector rows");
460  head.append("DETCOLS", m_detCols, "WFS detector cols");
461  head.append("CALAMP", m_calAmp, "DM Calibration amplitude");
462  head.append("NMODES", m_nModes, "Number of modes included in the response matrix.");
463 
464  //ff.write(fname, m_rImages.data(), m_rImages.rows(), m_rImages.cols(), m_rImages.planes(), &head);
465  ff.write(fname, m_rImages, head);
466 }
467 
468 } //namespace sim
469 } //namespace AO
470 } //namespace mx
471 
472 #endif //directPhaseReconstructor_hpp
473 
474 
475 
void detCols(int dc)
Set the number of detector columns (m_detCols)
Eigen::Array< realT, -1, -1 > imageT
The type of the WFS image.
directPhaseReconstructorSpec specT
The specificaion type.
Eigen::Array< realT, -1, -1 > rmatT
The type of the response matrix.
void detRows(int dr)
Set the number of detector rows (m_detRows)
Class to manage interactions with a FITS file.
Definition: fitsFile.hpp:54
int write(const dataT *im, int d1, int d2, int d3, fitsHeader *head)
Write the contents of a raw array to the FITS file.
Definition: fitsFile.hpp:1301
int read(dataT *data)
Read the contents of the FITS file into an array.
Definition: fitsFile.hpp:828
Class to manage a complete fits header.
Definition: fitsHeader.hpp:52
void append(fitsHeaderCard card)
Append a fitsHeaderCard to the end of the header.
Definition: fitsHeader.cpp:156
constexpr units::realT k()
Boltzmann Constant.
Definition: constants.hpp:71
The mxlib c++ namespace.
Definition: mxError.hpp:107