8#ifndef deformableMirror_hpp
9#define deformableMirror_hpp
25#include "../../math/constants.hpp"
32#include "wavefront.hpp"
35#define BREAD_CRUMB std::cout << "DEBUG: " << __FILE__ << " " << __LINE__ << "\n";
49struct deformableMirrorSpec
52 std::string basisName;
55template <
typename _realT>
61 typedef std::complex<realT> complexT;
64 typedef wavefront<realT> wavefrontT;
67 typedef Eigen::Array<realT, Eigen::Dynamic, Eigen::Dynamic> imageT;
69 typedef deformableMirrorSpec specT;
74 std::string _basisName;
76 std::string m_pupilName;
83 int _settleTime_counter;
90 std::vector<size_t> m_idx;
94 Eigen::Array<realT, -1, -1> m_m2c;
97 improc::eigenCube<realT> m_infF;
100 cublasHandle_t *m_cublasHandle;
101 cuda::cudaPtr<realT> m_one;
102 cuda::cudaPtr<realT> m_alpha;
103 cuda::cudaPtr<realT> m_zero;
105 cuda::cudaPtr<realT> m_devM2c;
106 cuda::cudaPtr<realT> m_devInfF;
108 cuda::cudaPtr<realT> m_devModeCommands;
109 cuda::cudaPtr<realT> m_devActCommands;
110 cuda::cudaPtr<realT> m_devShape;
133 if( _commandFileOpen )
135 _commandFout.close();
139 template <
typename AOSysT>
140 void initialize( AOSysT &AOSys, specT &spec,
const std::string &pupil );
147 std::string basisName()
156 void settleTime(
int st );
164 void calAmp( realT ca );
170 void applyMode( wavefrontT &wf,
int modeNo, realT amp, realT lambda );
175 template <
typename commandT>
176 void setShape( commandT &commandV );
178 void applyShape( wavefrontT &wf, realT lambda );
180 double t0, t1, t_mm, t_sum;
183 bool _commandFileOpen;
184 std::string _commandFile;
185 std::ofstream _commandFout;
189 Eigen::Array<double, -1, -1> _pos, _map;
191 sigproc::psdFilter<realT, 2> m_filter;
193 bool m_applyFilter{
false };
195 void setFilter(
int width );
198template <
typename _realT>
199deformableMirror<_realT>::deformableMirror()
203 _settleTime_counter = 0;
209 _writeCommands =
false;
210 _commandFileOpen =
false;
219template <
typename _realT>
220template <
typename AOSysT>
221void deformableMirror<_realT>::initialize( AOSysT &AOSys, specT &spec,
const std::string &pupil )
224 _basisName = spec.basisName;
227 fits::fitsFile<_realT> ff;
231 ff.read( m_pupil, pName );
232 m_pupilSum = m_pupil.sum();
236 for(
int rr = 0; rr < m_pupil.rows(); ++rr )
238 for(
int cc = 0; cc < m_pupil.cols(); ++cc )
240 if( m_pupil( rr, cc ) == 1 )
242 m_idx.push_back( kk );
248 if( _name ==
"modalDM" )
250 std::cerr <<
"modalDM\n";
253 ifName = mx::AO::path::basis::modes( _basisName );
255 ff.read( m_infF, ifName );
257 m_nActs = m_infF.planes();
258 m_nRows = m_infF.rows();
259 m_nCols = m_infF.cols();
261 m_m2c.resize( m_nActs, m_nActs );
264 for(
int i = 0; i < m_m2c.rows(); ++i )
269 m_cublasHandle = &AOSys.m_cublasHandle;
273 m_one.upload( &one, 1 );
276 realT alpha = -1 * _calAmp;
277 m_alpha.upload( &alpha, 1 );
284 modft.resize( m_idx.size(), m_nActs );
286 for(
int pp = 0; pp < m_nActs; ++pp )
288 for(
int nn = 0; nn < m_idx.size(); ++nn )
290 *( modft.data() + pp * m_idx.size() + nn ) = *( m_infF.image( pp ).data() + m_idx[nn] );
294 m_devInfF.upload( modft.data(), modft.rows() * modft.cols() );
296 m_devM2c.upload( m_m2c.data(), m_m2c.rows() * m_m2c.cols() );
298 m_devModeCommands.resize( m_nActs );
299 m_devActCommands.resize( m_nActs );
305 std::cerr <<
"Non-modal DM is currently not implemented\n";
312 improc::eigenCube<realT> infFLoad;
313 ff.read(infFLoad, ifName);
315 realT
c = 0.5*(infFLoad.rows()-1);
316 realT w = 0.5*(m_pupil.rows()-1);
318 m_infF.resize( m_pupil.rows(), m_pupil.cols(), infFLoad.planes());
320 for(
int i=0;i<infFLoad.planes(); ++i)
322 m_infF.image(i) = infFLoad.image(i).block( c-w, c-w, m_pupil.rows(), m_pupil.rows());
329 ff.read(m_m2c, m2cName);
334 ff.read(_pos, posName);
338 _shape.resize( m_nRows, m_nCols );
347template <
typename _realT>
348int deformableMirror<_realT>::settleTime()
353template <
typename _realT>
354void deformableMirror<_realT>::settleTime(
int st )
358 std::cerr <<
"DM: settleTime must be > 1. Correcting.\n";
365template <
typename _realT>
366_realT deformableMirror<_realT>::calAmp()
371template <
typename _realT>
372void deformableMirror<_realT>::calAmp( realT ca )
377 realT alpha = -1 * _calAmp;
378 m_alpha.upload( &alpha, 1 );
382template <
typename _realT>
383int deformableMirror<_realT>::nModes()
388template <
typename _realT>
389void deformableMirror<_realT>::applyMode( wavefrontT &wf,
int modeNo, realT amp, realT lambda )
392 Eigen::Array<_realT, -1, -1> commandV( 1, nModes() );
395 commandV( 0, modeNo ) = 1;
397 Eigen::Array<_realT, -1, -1>
c;
400 c = m_m2c.matrix() * commandV.matrix().transpose();
404 imageT shape( m_nRows, m_nCols );
406 shape =
c( 0, 0 ) * m_infF.image( 0 );
411 Eigen::Array<_realT, -1, -1> tmp;
414 tmp.setZero( m_nRows, m_nCols );
416#pragma omp for schedule( static )
417 for(
int i = 1; i < m_nActs; ++i )
419 tmp +=
c( i, 0 ) * m_infF.image( i );
431template <
typename realT>
432void makeMap( Eigen::Array<realT, -1, -1> &map, Eigen::Array<realT, -1, -1> &pos, Eigen::Array<realT, -1, -1> &act )
435 realT minx = pos.row( 0 ).minCoeff();
436 realT maxx = pos.row( 0 ).maxCoeff();
442 dx = fabs( pos( 0, i ) - pos( 0, 0 ) );
446 realT miny = pos.row( 1 ).minCoeff();
447 realT maxy = pos.row( 1 ).maxCoeff();
454 dy = fabs( pos( 1, i ) - pos( 1, 0 ) );
458 int nx = ( maxx - minx ) / dx + 1;
459 int ny = ( maxy - miny ) / dy + 1;
461 map.resize( nx, ny );
466 for(
int j = 0; j < pos.cols(); ++j )
468 x = ( pos( 0, j ) - minx ) / dx;
470 y = ( pos( 1, j ) - miny ) / dy;
472 map( (
int)x, (
int)y ) = act( j, 0 );
476template <
typename _realT>
477template <
typename commandT>
478void deformableMirror<_realT>::setShape( commandT &commandV )
483 std::cerr <<
"DM: new command received while still settling.\n";
487 static Eigen::Array<_realT, -1, -1>
c;
490 m_devModeCommands.upload( commandV.measurement.data(), commandV.measurement.size() );
492 cublasStatus_t stat = cuda::cublasTgemv<realT>( *m_cublasHandle,
500 m_devActCommands() );
502 if( stat != CUBLAS_STATUS_SUCCESS )
504 std::cerr <<
"cublas error\n";
511 Eigen::Map<Eigen::Array<realT, -1, -1>> commandV_measurement(
512 commandV.measurement.data(), 1, commandV.measurement.size() );
513 c = -1 * _calAmp * m_m2c.matrix() * commandV_measurement.matrix().transpose();
519 if(_commandLimit > 0)
522 realT r1 = sqrt( pow(_pos(0,1) - _pos(0,0),2) + pow(_pos(1,1) - _pos(1,0),2));
528 for(
int i=0; i< _pos.cols(); ++i)
530 for(
int j=i+1; j< _pos.cols(); ++j)
532 r = sqrt( pow(_pos(0,j) - _pos(0,i),2) + pow(_pos(1,j) - _pos(1,i),2));
534 if( fabs(r1 - r) < .01 )
536 realT iact = fabs(
c(i,0) -
c(j,0) );
537 if( iact > _commandLimit )
539 std::cerr <<
"Limited Actuators " << i <<
" " << j <<
"\n";
541 c(i,0) *= _commandLimit/iact;
542 c(j,0) *= _commandLimit/iact;
547 if(nLimited > 0) std::cerr << nLimited <<
" strokes limited\n";
552 if(_commandLimit > 0 )
554 for(
int i=0; i <
c.rows(); ++i)
556 if(
c(i,0) > _commandLimit )
c(i,0) = _commandLimit;
557 if(
c(i,0) < -1*_commandLimit )
c(i,0) = -1*_commandLimit;
566 if(!_commandFileOpen)
568 _commandFout.open( _commandFile );
569 _commandFout << std::scientific;
570 _commandFileOpen =
true;
573 _commandFout << commandV.iterNo <<
"> ";
574 for(
int i=0; i<
c.rows(); ++i)
576 _commandFout <<
c(i,0) <<
" ";
578 _commandFout << std::endl;
585 for(
int i=0; i< m_nActs; ++i)
587 if( std::isnan(
c(i,0) ) || !std::isfinite(
c(i,0)))
596 std::cerr <<
"SKIP FRAME\n";
604 static std::vector<realT> tmp;
605 tmp.resize( m_idx.size() );
607 m_devShape.resize( m_idx.size() );
608 m_devShape.initialize();
610 for(
int i = 0; i < m_nActs; ++i )
613 cuda::cublasTaxpy<realT>(
614 *m_cublasHandle, m_idx.size(), m_devActCommands() + i, m_devInfF() + i * m_idx.size(), 1, m_devShape(), 1 );
617 m_devShape.download( tmp.data() );
619 _nextShape.setZero();
621 realT *imP = _nextShape.data();
623 for(
size_t n = 0; n < m_idx.size(); ++n )
624 imP[m_idx[n]] = tmp[n];
628 _nextShape =
c( 0, 0 ) * m_infF.image( 0 );
632 Eigen::Array<_realT, -1, -1> tmp;
633 tmp.resize( m_nRows, m_nCols );
636 realT *tmpP = tmp.data();
638 for(
int i = 1; i < m_nActs; ++i )
640 realT *imP = m_infF.image( i ).data();
641 for(
size_t n = 0; n < m_idx.size(); ++n )
642 *( tmpP + m_idx[n] ) +=
c( i, 0 ) * *( imP + m_idx[n] );
646 realT *imP = _nextShape.data();
647 for(
size_t n = 0; n < m_idx.size(); ++n )
648 *( imP + m_idx[n] ) += *( tmpP + m_idx[n] );
657 std::cerr <<
"DM filtering\n";
658 m_filter.filter( _nextShape );
664 _settleTime_counter = 0;
665 _settlingIter = commandV.iterNo;
672template <
typename _realT>
673void deformableMirror<_realT>::applyShape( wavefrontT &wf, realT lambda )
682 _shape = _oldShape + ( _nextShape - _oldShape ) * ( (realT)_settleTime_counter + 1.0 ) / ( (realT)_settleTime );
684 realT mn = ( _shape * m_pupil ).sum() / m_pupilSum;
685 _shape = ( _shape - mn ) * m_pupil;
687 ++_settleTime_counter;
689 if( _settleTime_counter >= _settleTime )
692 _settledIter = _settlingIter;
703#ifdef MXAO_DIAG_LOOPCOUNTS
704 std::cerr <<
"DM " << m_nActs <<
" Shape applied: " << wf.iterNo <<
" " << _settledIter <<
"\n";
708template <
typename _realT>
709void deformableMirror<_realT>::setFilter(
int width )
711 int nr = _shape.rows();
712 int nc = _shape.cols();
716 filterMask.resize( nr, nc );
717 filterMask.setZero();
719 filterMask.block( 0, 0, width + 1, width + 1 ).setConstant( 1.0 );
720 filterMask.block( 0, nc - width, width + 1, width ).setConstant( 1.0 );
721 filterMask.block( nr - width, 0, width, width + 1 ).setConstant( 1.0 );
722 filterMask.block( nr - width, nc - width, width, width ).setConstant( 1.0 );
724 m_filter.psdSqrt( filterMask, 1.0 / _shape.rows(), 1.0 / _shape.cols() );
Standardized paths for the mx::AO system.
std::string M2c(const std::string &dmName, const std::string &basisName, bool create=false)
The path for the modes-to-commands (M2c) matrix for a deformable mirror (DM) and a basis set.
std::string pupilFile(const std::string &pupilName, bool create=false)
The path for the pupil FITS file.
std::string actuatorPositions(const std::string &dmName, bool create=false)
The path for the deformable mirror (DM) actuator positions.
std::string influenceFunctions(const std::string &dmName, bool create=false)
The path for the deformable mirror (DM) influence functions.
A wrapper for cuda device pointers.
An image cube with an Eigen API.
Declares and defines a class to work with a FITS file.
constexpr units::realT c()
The speed of light.
Eigen::Array< scalarT, -1, -1 > eigenImage
Definition of the eigenImage type, which is an alias for Eigen::Array.
constexpr T two_pi()
Get the value of 2pi.
typeT get_curr_time()
Get the current system time in seconds.
Utilities for modeling image formation.
Declares and defines a class for filtering with PSDs.
A utility to read in columns from a text file.
A template interface to cuBlas.
Utilities for working with time.