8#ifndef deformableMirror_hpp
9#define deformableMirror_hpp
13#include "../../wfp/imagingUtils.hpp"
14#include "../../sys/timeUtils.hpp"
15#include "../../ioutils/fits/fitsFile.hpp"
17#include "../../ioutils/readColumns.hpp"
19#include "../../math/constants.hpp"
21#include "../../math/cuda/cudaPtr.hpp"
22#include "../../math/cuda/templateCublas.hpp"
24#include "../aoPaths.hpp"
25#include "wavefront.hpp"
28#define BREAD_CRUMB std::cout << "DEBUG: " << __FILE__ << " " << __LINE__ << "\n";
42struct deformableMirrorSpec
45 std::string basisName;
48template <
typename _realT>
54 typedef std::complex<realT> complexT;
57 typedef wavefront<realT> wavefrontT;
60 typedef Eigen::Array<realT, Eigen::Dynamic, Eigen::Dynamic> imageT;
62 typedef deformableMirrorSpec specT;
67 std::string _basisName;
69 std::string m_pupilName;
76 int _settleTime_counter;
83 std::vector<size_t> m_idx;
87 Eigen::Array<realT, -1, -1> m_m2c;
90 improc::eigenCube<realT> m_infF;
93 cublasHandle_t *m_cublasHandle;
94 cuda::cudaPtr<realT> m_one;
95 cuda::cudaPtr<realT> m_alpha;
96 cuda::cudaPtr<realT> m_zero;
98 cuda::cudaPtr<realT> m_devM2c;
99 cuda::cudaPtr<realT> m_devInfF;
101 cuda::cudaPtr<realT> m_devModeCommands;
102 cuda::cudaPtr<realT> m_devActCommands;
103 cuda::cudaPtr<realT> m_devShape;
126 if( _commandFileOpen )
128 _commandFout.close();
132 template <
typename AOSysT>
133 void initialize( AOSysT &AOSys, specT &spec,
const std::string &pupil );
140 std::string basisName()
149 void settleTime(
int st );
157 void calAmp( realT ca );
163 void applyMode( wavefrontT &wf,
int modeNo, realT amp, realT lambda );
168 template <
typename commandT>
169 void setShape( commandT &commandV );
171 void applyShape( wavefrontT &wf, realT lambda );
173 double t0, t1, t_mm, t_sum;
176 bool _commandFileOpen;
177 std::string _commandFile;
178 std::ofstream _commandFout;
182 Eigen::Array<double, -1, -1> _pos, _map;
184 sigproc::psdFilter<realT, 2> m_filter;
186 bool m_applyFilter{
false };
188 void setFilter(
int width );
191template <
typename _realT>
192deformableMirror<_realT>::deformableMirror()
196 _settleTime_counter = 0;
202 _writeCommands =
false;
203 _commandFileOpen =
false;
212template <
typename _realT>
213template <
typename AOSysT>
214void deformableMirror<_realT>::initialize( AOSysT &AOSys, specT &spec,
const std::string &pupil )
217 _basisName = spec.basisName;
220 fits::fitsFile<_realT> ff;
224 ff.read( m_pupil, pName );
225 m_pupilSum = m_pupil.sum();
229 for(
int rr = 0; rr < m_pupil.rows(); ++rr )
231 for(
int cc = 0; cc < m_pupil.cols(); ++cc )
233 if( m_pupil( rr, cc ) == 1 )
235 m_idx.push_back( kk );
241 if( _name ==
"modalDM" )
243 std::cerr <<
"modalDM\n";
246 ifName = mx::AO::path::basis::modes( _basisName );
248 ff.read( m_infF, ifName );
250 m_nActs = m_infF.planes();
251 m_nRows = m_infF.rows();
252 m_nCols = m_infF.cols();
254 m_m2c.resize( m_nActs, m_nActs );
257 for(
int i = 0; i < m_m2c.rows(); ++i )
262 m_cublasHandle = &AOSys.m_cublasHandle;
266 m_one.upload( &one, 1 );
269 realT alpha = -1 * _calAmp;
270 m_alpha.upload( &alpha, 1 );
277 modft.resize( m_idx.size(), m_nActs );
279 for(
int pp = 0; pp < m_nActs; ++pp )
281 for(
int nn = 0; nn < m_idx.size(); ++nn )
283 *( modft.data() + pp * m_idx.size() + nn ) = *( m_infF.image( pp ).data() + m_idx[nn] );
287 m_devInfF.upload( modft.data(), modft.rows() * modft.cols() );
289 m_devM2c.upload( m_m2c.data(), m_m2c.rows() * m_m2c.cols() );
291 m_devModeCommands.resize( m_nActs );
292 m_devActCommands.resize( m_nActs );
298 std::cerr <<
"Non-modal DM is currently not implemented\n";
305 improc::eigenCube<realT> infFLoad;
306 ff.read(infFLoad, ifName);
308 realT
c = 0.5*(infFLoad.rows()-1);
309 realT w = 0.5*(m_pupil.rows()-1);
311 m_infF.resize( m_pupil.rows(), m_pupil.cols(), infFLoad.planes());
313 for(
int i=0;i<infFLoad.planes(); ++i)
315 m_infF.image(i) = infFLoad.image(i).block( c-w, c-w, m_pupil.rows(), m_pupil.rows());
322 ff.read(m_m2c, m2cName);
327 ff.read(_pos, posName);
331 _shape.resize( m_nRows, m_nCols );
340template <
typename _realT>
341int deformableMirror<_realT>::settleTime()
346template <
typename _realT>
347void deformableMirror<_realT>::settleTime(
int st )
351 std::cerr <<
"DM: settleTime must be > 1. Correcting.\n";
358template <
typename _realT>
359_realT deformableMirror<_realT>::calAmp()
364template <
typename _realT>
365void deformableMirror<_realT>::calAmp( realT ca )
370 realT alpha = -1 * _calAmp;
371 m_alpha.upload( &alpha, 1 );
375template <
typename _realT>
376int deformableMirror<_realT>::nModes()
381template <
typename _realT>
382void deformableMirror<_realT>::applyMode( wavefrontT &wf,
int modeNo, realT amp, realT lambda )
385 Eigen::Array<_realT, -1, -1> commandV( 1, nModes() );
388 commandV( 0, modeNo ) = 1;
390 Eigen::Array<_realT, -1, -1>
c;
393 c = m_m2c.matrix() * commandV.matrix().transpose();
397 imageT shape( m_nRows, m_nCols );
399 shape =
c( 0, 0 ) * m_infF.image( 0 );
404 Eigen::Array<_realT, -1, -1> tmp;
407 tmp.setZero( m_nRows, m_nCols );
409#pragma omp for schedule( static )
410 for(
int i = 1; i < m_nActs; ++i )
412 tmp +=
c( i, 0 ) * m_infF.image( i );
424template <
typename realT>
425void makeMap( Eigen::Array<realT, -1, -1> &map, Eigen::Array<realT, -1, -1> &pos, Eigen::Array<realT, -1, -1> &act )
428 realT minx = pos.row( 0 ).minCoeff();
429 realT maxx = pos.row( 0 ).maxCoeff();
435 dx = fabs( pos( 0, i ) - pos( 0, 0 ) );
439 realT miny = pos.row( 1 ).minCoeff();
440 realT maxy = pos.row( 1 ).maxCoeff();
447 dy = fabs( pos( 1, i ) - pos( 1, 0 ) );
451 int nx = ( maxx - minx ) / dx + 1;
452 int ny = ( maxy - miny ) / dy + 1;
454 map.resize( nx, ny );
459 for(
int j = 0; j < pos.cols(); ++j )
461 x = ( pos( 0, j ) - minx ) / dx;
463 y = ( pos( 1, j ) - miny ) / dy;
465 map( (
int)x, (
int)y ) = act( j, 0 );
469template <
typename _realT>
470template <
typename commandT>
471void deformableMirror<_realT>::setShape( commandT &commandV )
476 std::cerr <<
"DM: new command received while still settling.\n";
480 static Eigen::Array<_realT, -1, -1>
c;
483 m_devModeCommands.upload( commandV.measurement.data(), commandV.measurement.size() );
485 cublasStatus_t stat = cuda::cublasTgemv<realT>( *m_cublasHandle,
493 m_devActCommands() );
495 if( stat != CUBLAS_STATUS_SUCCESS )
497 std::cerr <<
"cublas error\n";
504 Eigen::Map<Eigen::Array<realT, -1, -1>> commandV_measurement(
505 commandV.measurement.data(), 1, commandV.measurement.size() );
506 c = -1 * _calAmp * m_m2c.matrix() * commandV_measurement.matrix().transpose();
512 if(_commandLimit > 0)
515 realT r1 = sqrt( pow(_pos(0,1) - _pos(0,0),2) + pow(_pos(1,1) - _pos(1,0),2));
521 for(
int i=0; i< _pos.cols(); ++i)
523 for(
int j=i+1; j< _pos.cols(); ++j)
525 r = sqrt( pow(_pos(0,j) - _pos(0,i),2) + pow(_pos(1,j) - _pos(1,i),2));
527 if( fabs(r1 - r) < .01 )
529 realT iact = fabs(
c(i,0) -
c(j,0) );
530 if( iact > _commandLimit )
532 std::cerr <<
"Limited Actuators " << i <<
" " << j <<
"\n";
534 c(i,0) *= _commandLimit/iact;
535 c(j,0) *= _commandLimit/iact;
540 if(nLimited > 0) std::cerr << nLimited <<
" strokes limited\n";
545 if(_commandLimit > 0 )
547 for(
int i=0; i <
c.rows(); ++i)
549 if(
c(i,0) > _commandLimit )
c(i,0) = _commandLimit;
550 if(
c(i,0) < -1*_commandLimit )
c(i,0) = -1*_commandLimit;
559 if(!_commandFileOpen)
561 _commandFout.open( _commandFile );
562 _commandFout << std::scientific;
563 _commandFileOpen =
true;
566 _commandFout << commandV.iterNo <<
"> ";
567 for(
int i=0; i<
c.rows(); ++i)
569 _commandFout <<
c(i,0) <<
" ";
571 _commandFout << std::endl;
578 for(
int i=0; i< m_nActs; ++i)
580 if( std::isnan(
c(i,0) ) || !std::isfinite(
c(i,0)))
589 std::cerr <<
"SKIP FRAME\n";
597 static std::vector<realT> tmp;
598 tmp.resize( m_idx.size() );
600 m_devShape.resize( m_idx.size() );
601 m_devShape.initialize();
603 for(
int i = 0; i < m_nActs; ++i )
606 cuda::cublasTaxpy<realT>(
607 *m_cublasHandle, m_idx.size(), m_devActCommands() + i, m_devInfF() + i * m_idx.size(), 1, m_devShape(), 1 );
610 m_devShape.download( tmp.data() );
612 _nextShape.setZero();
614 realT *imP = _nextShape.data();
616 for(
size_t n = 0; n < m_idx.size(); ++n )
617 imP[m_idx[n]] = tmp[n];
621 _nextShape =
c( 0, 0 ) * m_infF.image( 0 );
625 Eigen::Array<_realT, -1, -1> tmp;
626 tmp.resize( m_nRows, m_nCols );
629 realT *tmpP = tmp.data();
631 for(
int i = 1; i < m_nActs; ++i )
633 realT *imP = m_infF.image( i ).data();
634 for(
size_t n = 0; n < m_idx.size(); ++n )
635 *( tmpP + m_idx[n] ) +=
c( i, 0 ) * *( imP + m_idx[n] );
639 realT *imP = _nextShape.data();
640 for(
size_t n = 0; n < m_idx.size(); ++n )
641 *( imP + m_idx[n] ) += *( tmpP + m_idx[n] );
650 std::cerr <<
"DM filtering\n";
651 m_filter.filter( _nextShape );
657 _settleTime_counter = 0;
658 _settlingIter = commandV.iterNo;
665template <
typename _realT>
666void deformableMirror<_realT>::applyShape( wavefrontT &wf, realT lambda )
675 _shape = _oldShape + ( _nextShape - _oldShape ) * ( (realT)_settleTime_counter + 1.0 ) / ( (realT)_settleTime );
677 realT mn = ( _shape * m_pupil ).sum() / m_pupilSum;
678 _shape = ( _shape - mn ) * m_pupil;
680 ++_settleTime_counter;
682 if( _settleTime_counter >= _settleTime )
685 _settledIter = _settlingIter;
696#ifdef MXAO_DIAG_LOOPCOUNTS
697 std::cerr <<
"DM " << m_nActs <<
" Shape applied: " << wf.iterNo <<
" " << _settledIter <<
"\n";
701template <
typename _realT>
702void deformableMirror<_realT>::setFilter(
int width )
704 int nr = _shape.rows();
705 int nc = _shape.cols();
707 typename wfsImageT<_realT>::imageT filterMask;
709 filterMask.resize( nr, nc );
710 filterMask.setZero();
712 filterMask.block( 0, 0, width + 1, width + 1 ).setConstant( 1.0 );
713 filterMask.block( 0, nc - width, width + 1, width ).setConstant( 1.0 );
714 filterMask.block( nr - width, 0, width, width + 1 ).setConstant( 1.0 );
715 filterMask.block( nr - width, nc - width, width, width ).setConstant( 1.0 );
717 m_filter.psdSqrt( filterMask, 1.0 / _shape.rows(), 1.0 / _shape.cols() );
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.
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 floatT six_fifths()
Return 6/5 in the specified precision.
typeT get_curr_time()
Get the current system time in seconds.