mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
Loading...
Searching...
No Matches
pywfsSlopeReconstructor.hpp
Go to the documentation of this file.
1/** \file pywfsSlopeReconstructor.hpp
2 * \brief Declares the pyramid-wavefront-sensor slope reconstructor.
3 * \author Jared R. Males (jaredmales@gmail.com)
4 */
5
6#ifndef __pywfsSlopeReconstructor_hpp__
7#define __pywfsSlopeReconstructor_hpp__
8
9#include <string>
10
11#include "../../ao/aoPaths.hpp"
15
16namespace mx
17{
18namespace AO
19{
20namespace sim
21{
22
23struct pywfsSlopeReconstructorSpec
24{
25 std::string dmName;
26 std::string basisName;
27
28 std::string rMatId;
29};
30
31/// A Pyramid Wavefront Sensor slope reconstructor.
32/** Calculates slopes, normalized by total flux in the image.
33 */
34template <typename _floatT>
36{
37 public:
38 typedef _floatT floatT;
39
40 /// The type of the measurement (i.e. the slope vector)
41 // typedef Eigen::Array<floatT,-1,-1> measurementT;
42
43 /// The type of the WFS image
44 typedef Eigen::Array<floatT, -1, -1> imageT;
45
46 /// The type of the response matrix
47 typedef Eigen::Array<floatT, -1, -1> rmatT;
48
49 typedef pywfsSlopeReconstructorSpec specT;
50
51 protected:
52 Eigen::Array<floatT, -1, -1> _recon; ///< The reconstructor matrix.
53
54 int _maskType; /// 0 is centrally obscured circle, 1 is supplied by fits files
55
56 floatT _maskRadius; ///< The radius of the quadrant mask
57 floatT _maskObscuration; ///< The central obscuration of the quadrant mask
58
59 std::string _maskFile; ///< The name of the quadrant mask file
60
61 bool _maskMade; ///< Whether or not the mask has been made
62
63 Eigen::Array<floatT, -1, -1> _quadMask; ///< The quadrant mask
64 void calcMask(); ///< Calculates the quadrant mask
65 int _measurementSize; ///< The number of slopes in the measurement
66
67 floatT _calAmp; ///< The calibration amplitude used for response matrix acquisition
68
69 int _nModes; ///< The number of modes to be reconstructed
70
71 int _detRows; ///< The size of the WFS image, in rows
72 int _detCols; ///< The size of the WFS image, in columns
73
74 imageT _rMat; ///< The response matrix
76
77 public:
78 int _binFact; ///< The binning to apply before reconstructing.
79
80 /// Default c'tor
82
83 template <typename AOSysT>
84 void initialize( AOSysT &AOSys, specT &spec )
85 {
86 std::string recMatrix = mx::AO::path::sys::cal::iMat(
87 AOSys._sysName, spec.dmName, AOSys._wfsName, AOSys._pupilName, spec.basisName, spec.rMatId );
88 loadRecon( recMatrix );
89 }
90
91 /// Get the quadrant mask radius (_maskRadius)
92 floatT maskRadius();
93
94 /// Set the quadrant mask radius (_maskRadius)
95 /** Calling this will cause the quadrant mask to be recalculated next time it is needed.
96 *
97 * \param mr [in] the new mask radius
98 */
99 void maskRadius( floatT mr );
100
101 /// Get the quadrant mask central obscuration ratio (_maskObscuration)
102 floatT maskObscuration();
103
104 /// Set the quadrant mask central obscuration ratio (_maskObscuration)
105 /** Calling this will cause the quadrant mask to be recalculated next time it is needed.
106 *
107 * \param mo [in] the new central obscuration ratio
108 */
109 void maskObscuration( floatT mo );
110
111 /// Get the quadrant mask file name (_maskFile)
112 std::string maskFile();
113
114 /// Set the quadrant mask file name (_maskFile)
115 /** Calling this will cause the quadrant mask to be reloaded next time it is needed.
116 *
117 * \param mf [in] the new mask file
118 */
119 void maskFile( const std::string &mf );
120
121 /// Get the calibration amplitude used in response matrix acquisition (_calAmp)
122 floatT calAmp();
123
124 /// Set the calibration amplitude used in response matrix acquisition (_calAmp)
125 /**
126 * \param ca [in] the new calibration amplitude
127 */
128 void calAmp( floatT ca );
129
130 /// Get the number of modes (_nModes)
131 int nModes();
132
133 /// Get the number of detector rows (_detRows)
134 int detRows();
135
136 /// Set the number of detector rows (_detRows)
137 void detRows( int dr );
138
139 /// Get the number of detector columns (_detCols)
140 int detCols();
141
142 /// Set the number of detector columns (_detCols)
143 void detCols( int dc );
144
145 /// Load the reconstrutor from the specified FITS file
146 /**
147 * \param fname is the name of the FITS file, including path
148 */
149 void loadRecon( std::string fname );
150
151 /// Return the size of the unbinned measurement
152 int measurementSize();
153
154 /// Calculate the slope measurement
155 /**
156 * \param slopes [out] a (_measurementSize X 2) array of slopes
157 * \param wfsImage [in] the WFS image from which to measure the slopes
158 */
159 template <typename measurementT, typename wfsImageT>
160 void calcMeasurement( measurementT &slopes, wfsImageT &wfsImage );
161
162 /// Reconstruct the wavefront from the input image, producing the modal amplitude vector
163 template <typename measurementT, typename wfsImageT>
164 void reconstruct( measurementT &commandVect, wfsImageT &wfsImage );
165
166 /// Initialize the response matrix for acquisition
167 /**
168 * \param nmodes the number of modes
169 * \param calamp the calibration amplitude
170 * \param detrows the number of detector rows
171 * \param detcols the number of detector columns
172 */
173 void initializeRMat( int nmodes, floatT calamp, int detrows, int detcols );
174
175 /// Accumalte the next measurement in the response matrix
176 /**
177 * \param i the measurement index
178 * \param measureVec is the i-th measurement vector
179 */
180 template <typename measurementT>
181 void accumulateRMat( int i, measurementT &measureVec );
182
183 template <typename measurementT, typename wfsImageT>
184 void accumulateRMat( int i, measurementT &measureVec, wfsImageT &wfsImage );
185
186 /// Write the accumulated response matrix to disk
187 /**
188 * \param fname the name, including path, of the response matrix
189 */
190 void saveRMat( std::string fname );
191
192 void saveRImages( std::string fname );
193};
194
195template <typename floatT>
205
206template <typename floatT>
211
212template <typename floatT>
214{
215 _maskRadius = mr;
216 _maskType = 0;
217 _maskMade = false;
218}
219
220template <typename floatT>
225
226template <typename floatT>
228{
229 _maskObscuration = mo;
230 _maskType = 0;
231 _maskMade = false;
232}
233
234template <typename floatT>
236{
237 return _maskFile;
238}
239
240template <typename floatT>
241void pywfsSlopeReconstructor<floatT>::maskFile( const std::string &mf )
242{
243 _maskFile = mf;
244 _maskType = 1;
245 _maskMade = false;
246}
247
248template <typename floatT>
253
254template <typename floatT>
256{
257 _calAmp = ca;
258}
259
260template <typename floatT>
265
266template <typename floatT>
271
272template <typename floatT>
274{
275 _detRows = dr;
276 _maskMade = false;
277}
278
279template <typename floatT>
284
285template <typename floatT>
287{
288 _detCols = dc;
289 _maskMade = false;
290}
291
292template <typename floatT>
294{
297
298 ff.read( _recon, head, fname );
299
300 _maskRadius = head["MASKRAD"].value<floatT>();
301 _maskObscuration = head["MASKOBS"].value<floatT>();
302 _maskFile = head["MASKFILE"].value<std::string>();
303
304 if( _maskFile != "" )
305 _maskType = 1;
306
307 _calAmp = head["CALAMP"].value<floatT>();
308
309 _nModes = head["NMODES"].value<int>();
310
311 _detRows = head["DETROWS"].value<int>();
312 _detCols = head["DETCOLS"].value<int>();
313
314 _maskMade = false;
315}
316
317template <typename floatT>
319{
320 if( _maskType == 1 )
321 {
323
324 std::cerr << "Loading Mask: " << _maskFile << "\n";
325 ff.read( _quadMask, _maskFile );
326 }
327 else
328 {
329 _quadMask.resize( 0.5 * _detRows / _binFact, 0.5 * _detCols / _binFact );
331 }
332
333 _measurementSize = 2 * _quadMask.sum(); // + 64*64;
334
335 _maskMade = true;
336
338 ff.write( "quadMask.fits", _quadMask );
339}
340
341template <typename floatT>
348
349template <typename floatT>
350template <typename measurementT, typename wfsImageT>
351void pywfsSlopeReconstructor<floatT>::calcMeasurement( measurementT &slopes, wfsImageT &wfsImage )
352{
353 if( !_maskMade )
354 calcMask();
355
356 imageT _wfsImage;
357
358 if( _binFact > 1 )
359 {
360 std::cout << "rebinning" << "\n";
361 _wfsImage.resize( wfsImage.image.rows() / _binFact, wfsImage.image.cols() / _binFact );
362 imageDownSample( _wfsImage, wfsImage.image );
363 }
364 else
365 {
366 _wfsImage = wfsImage.image;
367 }
368
369 int nsz = _wfsImage.rows();
370
371 int nPix = _quadMask.sum();
372
373 std::vector<int> x( nPix ), y( nPix );
374
375 int k = 0;
376 for( int i = 0; i < _quadMask.rows(); ++i )
377 {
378 for( int j = 0; j < _quadMask.rows(); ++j )
379 {
380 if( _quadMask( i, j ) == 1 )
381 {
382 x[k] = i;
383 y[k] = j;
384 ++k;
385 }
386 }
387 }
388
389 slopes.measurement.resize( 1, 2. * nPix ); // + 64*64); //wfsImage.tipImage.rows()*wfsImage.tipImage.cols());
390
391 floatT I0, I1, I2, I3;
392
393 floatT norm = _wfsImage.sum();
394
395 for( int i = 0; i < nPix; ++i )
396 {
397 I0 = _wfsImage( x[i], y[i] );
398 I1 = _wfsImage( x[i] + 0.5 * nsz, y[i] );
399 I2 = _wfsImage( x[i], y[i] + 0.5 * nsz );
400 I3 = _wfsImage( x[i] + 0.5 * nsz, y[i] + 0.5 * nsz );
401
402 if( norm == 0 )
403 {
404 slopes.measurement( 0, i ) = 0;
405 ;
406 slopes.measurement( 0, i + nPix ) = 0; //
407 }
408 else
409 {
410 slopes.measurement( 0, i ) = ( I0 + I1 - I2 - I3 ) / norm; //(I0+I1+I2+I3);
411 slopes.measurement( 0, i + nPix ) = ( I0 + I2 - I1 - I3 ) / norm; //(I0+I1+I2+I3);
412 }
413 }
414
415 /*
416 for(int i=0; i< wfsImage.tipImage.rows(); ++i)
417 {
418 for(int j=0;j<wfsImage.tipImage.cols(); ++j)
419 {
420 slopes.measurement(0, 2*nPix + i*wfsImage.tipImage.cols() + j) = wfsImage.tipImage(i,j);
421 }
422 }*/
423}
424
425template <typename floatT>
426template <typename measurementT, typename wfsImageT>
427void pywfsSlopeReconstructor<floatT>::reconstruct( measurementT &commandVect, wfsImageT &wfsImage )
428{
429 measurementT slopes;
430
431 calcMeasurement( slopes, wfsImage );
432
433 commandVect.measurement = slopes.measurement.matrix() * _recon.matrix();
434
435 commandVect.iterNo = wfsImage.iterNo;
436}
437
438template <typename floatT>
440{
441
442 _nModes = nModes;
443
444 calAmp( calamp );
445
448
449 _rMat.resize( measurementSize(), nModes );
450 _rMat.setZero();
451
452 _rImages.resize( _detRows, _detCols, _nModes );
453}
454
455template <typename floatT>
456template <typename measurementT>
457void pywfsSlopeReconstructor<floatT>::accumulateRMat( int i, measurementT &measureVec )
458{
459 _rMat.col( i ) = measureVec.measurement.row( 0 );
460}
461
462template <typename floatT>
463template <typename measurementT, typename wfsImageT>
464void pywfsSlopeReconstructor<floatT>::accumulateRMat( int i, measurementT &measureVec, wfsImageT &wfsImage )
465{
466 accumulateRMat( i, measureVec );
467
468 _rImages.image( i ) = wfsImage.image;
469}
470
471template <typename floatT>
473{
476
477 if( _maskType == 1 )
478 {
479 head.append( "MASKFILE", maskFile(), "Name of mask file" );
480 }
481 else
482 {
483 head.append( "MASKRAD", maskRadius(), "Mask radius, in pixels" );
484 head.append( "MASKOBS", maskObscuration(), "Mask fractional central obscuration" );
485 }
486
487 head.append( "DETROWS", _detRows, "WFS detector rows" );
488 head.append( "DETCOLS", _detCols, "WFS detector cols" );
489 head.append( "CALAMP", _calAmp, "DM Calibration amplitude" );
490 head.append( "NMODES", _nModes, "Number of modes included in the response matrix." );
491
492 // ff.write(fname, _rMat.data(), _rMat.rows(), _rMat.cols(), 1, &head);
493 ff.write( fname, _rMat, head );
494}
495
496template <typename floatT>
497void pywfsSlopeReconstructor<floatT>::saveRImages( std::string fname )
498{
501
502 if( _maskType == 1 )
503 {
504 head.append( "MASKFILE", maskFile(), "Name of mask file" );
505 }
506 else
507 {
508 head.append( "MASKRAD", maskRadius(), "Mask radius, in pixels" );
509 head.append( "MASKOBS", maskObscuration(), "Mask fractional central obscuration" );
510 }
511
512 head.append( "DETROWS", _detRows, "WFS detector rows" );
513 head.append( "DETCOLS", _detCols, "WFS detector cols" );
514 head.append( "CALAMP", _calAmp, "DM Calibration amplitude" );
515 head.append( "NMODES", _nModes, "Number of modes included in the response matrix." );
516
517 // ff.write(fname, _rImages.data(), _rImages.rows(), _rImages.cols(), _rImages.planes(), &head);
518 ff.write( fname, _rImages, head );
519}
520
521} // namespace sim
522} // namespace AO
523} // namespace mx
524
525#endif //__pywfsSlopeReconstructor_hpp__
Standardized paths for the mx::AO system.
std::string iMat(const std::string &sysName, const std::string &dmName, const std::string &wfsName, const std::string &pupilName, const std::string &basisName, const std::string &id, bool create=false)
Path for the system response interaction matrix.
Definition aoPaths.hpp:446
floatT calAmp()
Get the calibration amplitude used in response matrix acquisition (_calAmp).
int _detCols
The size of the WFS image, in columns.
void reconstruct(measurementT &commandVect, wfsImageT &wfsImage)
Reconstruct the wavefront from the input image, producing the modal amplitude vector.
int _detRows
The size of the WFS image, in rows.
int nModes()
Get the number of modes (_nModes).
floatT _maskRadius
0 is centrally obscured circle, 1 is supplied by fits files
std::string _maskFile
The name of the quadrant mask file.
void saveRMat(std::string fname)
Write the accumulated response matrix to disk.
floatT maskObscuration()
Get the quadrant mask central obscuration ratio (_maskObscuration).
Eigen::Array< floatT, -1, -1 > _recon
The reconstructor matrix.
Eigen::Array< floatT, -1, -1 > _quadMask
The quadrant mask.
int _nModes
The number of modes to be reconstructed.
int detCols()
Get the number of detector columns (_detCols).
int _measurementSize
The number of slopes in the measurement.
Eigen::Array< floatT, -1, -1 > imageT
The type of the measurement (i.e. the slope vector).
int measurementSize()
Return the size of the unbinned measurement.
bool _maskMade
Whether or not the mask has been made.
int _binFact
The binning to apply before reconstructing.
floatT _calAmp
The calibration amplitude used for response matrix acquisition.
void calcMeasurement(measurementT &slopes, wfsImageT &wfsImage)
Calculate the slope measurement.
void accumulateRMat(int i, measurementT &measureVec)
Accumalte the next measurement in the response matrix.
Eigen::Array< floatT, -1, -1 > rmatT
The type of the response matrix.
floatT _maskObscuration
The central obscuration of the quadrant mask.
int detRows()
Get the number of detector rows (_detRows).
void loadRecon(std::string fname)
Load the reconstrutor from the specified FITS file.
floatT maskRadius()
Get the quadrant mask radius (_maskRadius).
std::string maskFile()
Get the quadrant mask file name (_maskFile).
void initializeRMat(int nmodes, floatT calamp, int detrows, int detcols)
Initialize the response matrix for acquisition.
void calcMask()
Calculates the quadrant mask.
Class to manage interactions with a FITS file.
Definition fitsFile.hpp:84
error_t read(dataT *data)
Read the contents of the FITS file into an array.
error_t write(const dataT *im, int d1, int d2, int d3, fitsHeader< verboseT > *head)
Write the contents of a raw array to the FITS file.
Class to manage a FITS file metadata header and provide fast access to the cards by keyword.
error_t append(const fitsHeaderCard< verboseT > &card)
Append a fitsHeaderCard to the end of the header.
An image cube with an Eigen-like API.
Definition eigenCube.hpp:33
An image cube with an Eigen API.
Declares and defines a class to work with a FITS file.
int circularPupil(arrayT &m, typename arrayT::Scalar eps=0, typename arrayT::Scalar rad=0, typename arrayT::Scalar overscan=0)
Fill in an Eigen-like array with a circular pupil mask.
Utilities for modeling image formation.
The mxlib c++ namespace.
Definition mxlib.hpp:37