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"
31 #define BREAD_CRUMB std::cout << "DEBUG: " << __FILE__ << " " << __LINE__ << "\n";
45 struct deformableMirrorSpec
48 std::string basisName;
51 template<
typename _realT>
52 class deformableMirror
58 typedef std::complex<realT> complexT;
61 typedef wavefront<realT> wavefrontT;
64 typedef Eigen::Array< realT, Eigen::Dynamic, Eigen::Dynamic> imageT;
66 typedef deformableMirrorSpec specT;
72 std::string _basisName;
74 std::string m_pupilName;
81 int _settleTime_counter;
89 std::vector<size_t> m_idx;
95 Eigen::Array<realT, -1, -1> m_m2c;
98 improc::eigenCube<realT> m_infF;
101 cublasHandle_t *m_cublasHandle;
102 cuda::cudaPtr<realT> m_one;
103 cuda::cudaPtr<realT> m_alpha;
104 cuda::cudaPtr<realT> m_zero;
106 cuda::cudaPtr<realT> m_devM2c;
107 cuda::cudaPtr<realT> m_devInfF;
109 cuda::cudaPtr<realT> m_devModeCommands;
110 cuda::cudaPtr<realT> m_devActCommands;
111 cuda::cudaPtr<realT> m_devShape;
138 _commandFout.close();
142 template<
typename AOSysT>
143 void initialize( AOSysT & AOSys,
145 const std::string & pupil
153 std::string basisName()
163 void settleTime(
int st);
171 void calAmp(realT ca);
177 void applyMode(wavefrontT & wf,
int modeNo, realT amp, realT lambda);
182 template<
typename commandT>
183 void setShape(commandT & commandV);
185 void applyShape( wavefrontT & wf,
189 double t0, t1, t_mm, t_sum;
192 bool _commandFileOpen;
193 std::string _commandFile;
194 std::ofstream _commandFout;
198 Eigen::Array<double,-1,-1> _pos, _map;
200 sigproc::psdFilter<realT,2> m_filter;
202 bool m_applyFilter {
false};
204 void setFilter(
int width );
208 template<
typename _realT>
209 deformableMirror<_realT>::deformableMirror()
213 _settleTime_counter = 0;
219 _writeCommands =
false;
220 _commandFileOpen =
false;
229 template<
typename _realT>
230 template<
typename AOSysT>
231 void deformableMirror<_realT>::initialize( AOSysT & AOSys,
233 const std::string & pupil )
236 _basisName = spec.basisName;
239 fits::fitsFile<_realT> ff;
243 ff.read(m_pupil, pName);
244 m_pupilSum = m_pupil.sum();
248 for(
int rr=0;rr<m_pupil.rows();++rr)
250 for(
int cc=0;cc<m_pupil.cols();++cc)
252 if(m_pupil(rr,cc) == 1)
260 if(_name ==
"modalDM")
262 std::cerr <<
"modalDM\n";
265 ifName = mx::AO::path::basis::modes(_basisName);
267 ff.read(m_infF, ifName);
269 m_nActs = m_infF.planes();
270 m_nRows = m_infF.rows();
271 m_nCols = m_infF.cols();
273 m_m2c.resize( m_nActs, m_nActs);
276 for(
int i=0;i<m_m2c.rows();++i) m_m2c(i,i) = 1.0;
280 m_cublasHandle = &AOSys.m_cublasHandle;
284 m_one.upload(&one, 1);
287 realT alpha = -1*_calAmp;
288 m_alpha.upload(&alpha, 1);
295 modft.resize( m_idx.size(),m_nActs);
297 for(
int pp=0;pp<m_nActs;++pp)
299 for(
int nn=0; nn < m_idx.size(); ++nn)
301 *(modft.data() + pp*m_idx.size() + nn) = *(m_infF.image(pp).data() + m_idx[nn]);
305 m_devInfF.upload(modft.data(), modft.rows()*modft.cols());
307 m_devM2c.upload(m_m2c.data(), m_m2c.rows()*m_m2c.cols());
309 m_devModeCommands.resize(m_nActs);
310 m_devActCommands.resize(m_nActs);
317 std::cerr <<
"Non-modal DM is currently not implemented\n";
324 improc::eigenCube<realT> infFLoad;
325 ff.read(infFLoad, ifName);
327 realT
c = 0.5*(infFLoad.rows()-1);
328 realT w = 0.5*(m_pupil.rows()-1);
330 m_infF.resize( m_pupil.rows(), m_pupil.cols(), infFLoad.planes());
332 for(
int i=0;i<infFLoad.planes(); ++i)
334 m_infF.image(i) = infFLoad.image(i).block(
c-w,
c-w, m_pupil.rows(), m_pupil.rows());
341 ff.read(m_m2c, m2cName);
346 ff.read(_pos, posName);
351 _shape.resize(m_nRows, m_nCols);
362 template<
typename _realT>
363 int deformableMirror<_realT>::settleTime()
368 template<
typename _realT>
369 void deformableMirror<_realT>::settleTime(
int st)
373 std::cerr <<
"DM: settleTime must be > 1. Correcting.\n";
380 template<
typename _realT>
381 _realT deformableMirror<_realT>::calAmp()
386 template<
typename _realT>
387 void deformableMirror<_realT>::calAmp(realT ca)
392 realT alpha = -1*_calAmp;
393 m_alpha.upload(&alpha, 1);
399 template<
typename _realT>
400 int deformableMirror<_realT>::nModes()
406 template<
typename _realT>
407 void deformableMirror<_realT>::applyMode(wavefrontT & wf,
int modeNo, realT amp, realT lambda)
410 Eigen::Array<_realT,-1,-1> commandV(1, nModes());
413 commandV(0, modeNo) = 1;
415 Eigen::Array<_realT, -1, -1>
c;
418 c = m_m2c.matrix() * commandV.matrix().transpose();
422 imageT shape( m_nRows, m_nCols);
425 shape =
c(0,0)*m_infF.image(0);
431 Eigen::Array<_realT, -1, -1> tmp;
434 tmp.setZero(m_nRows, m_nCols);
436 #pragma omp for schedule(static)
437 for(
int i=1;i < m_nActs; ++i)
439 tmp +=
c(i,0) * m_infF.image(i);
448 wf.phase += 2*amp*shape*m_pupil*math::two_pi<realT>()/lambda;
452 template<
typename realT>
453 void makeMap( Eigen::Array<realT, -1, -1> & map, Eigen::Array<realT, -1, -1> & pos, Eigen::Array<realT, -1, -1> & act)
456 realT minx = pos.row(0).minCoeff();
457 realT maxx = pos.row(0).maxCoeff();
463 dx = fabs(pos(0,i)- pos(0,0));
467 realT miny = pos.row(1).minCoeff();
468 realT maxy = pos.row(1).maxCoeff();
475 dy = fabs(pos(1,i)- pos(1,0));
479 int nx = (maxx-minx)/dx + 1;
480 int ny = (maxy-miny)/dy + 1;
488 for(
int j=0;j < pos.cols(); ++j)
490 x = (pos(0,j) - minx)/dx;
492 y = ( pos(1,j) - miny ) / dy;
494 map( (
int) x, (
int) y) = act(j,0);
502 template<
typename _realT>
503 template<
typename commandT>
504 void deformableMirror<_realT>::setShape(commandT & commandV)
509 std::cerr <<
"DM: new command received while still settling.\n";
514 static Eigen::Array<_realT, -1, -1>
c;
517 m_devModeCommands.upload(commandV.measurement.data(), commandV.measurement.size());
519 cublasStatus_t stat = cuda::cublasTgemv<realT>(*m_cublasHandle, CUBLAS_OP_N, m_nActs, m_nActs, m_alpha(), m_devM2c(), m_devModeCommands(), m_zero(), m_devActCommands());
521 if(stat != CUBLAS_STATUS_SUCCESS)
523 std::cerr <<
"cublas error\n";
532 Eigen::Map<Eigen::Array<realT,-1,-1>> commandV_measurement(commandV.measurement.data(), 1, commandV.measurement.size());
533 c = -1*_calAmp*m_m2c.matrix() * commandV_measurement.matrix().transpose();
539 if(_commandLimit > 0)
542 realT r1 = sqrt( pow(_pos(0,1) - _pos(0,0),2) + pow(_pos(1,1) - _pos(1,0),2));
548 for(
int i=0; i< _pos.cols(); ++i)
550 for(
int j=i+1; j< _pos.cols(); ++j)
552 r = sqrt( pow(_pos(0,j) - _pos(0,i),2) + pow(_pos(1,j) - _pos(1,i),2));
554 if( fabs(r1 - r) < .01 )
556 realT iact = fabs(
c(i,0) -
c(j,0) );
557 if( iact > _commandLimit )
559 std::cerr <<
"Limited Actuators " << i <<
" " << j <<
"\n";
561 c(i,0) *= _commandLimit/iact;
562 c(j,0) *= _commandLimit/iact;
567 if(nLimited > 0) std::cerr << nLimited <<
" strokes limited\n";
572 if(_commandLimit > 0 )
574 for(
int i=0; i <
c.rows(); ++i)
576 if(
c(i,0) > _commandLimit )
c(i,0) = _commandLimit;
577 if(
c(i,0) < -1*_commandLimit )
c(i,0) = -1*_commandLimit;
586 if(!_commandFileOpen)
588 _commandFout.open( _commandFile );
589 _commandFout << std::scientific;
590 _commandFileOpen =
true;
593 _commandFout << commandV.iterNo <<
"> ";
594 for(
int i=0; i<
c.rows(); ++i)
596 _commandFout <<
c(i,0) <<
" ";
598 _commandFout << std::endl;
605 for(
int i=0; i< m_nActs; ++i)
607 if( std::isnan(
c(i,0) ) || !std::isfinite(
c(i,0)))
616 std::cerr <<
"SKIP FRAME\n";
624 static std::vector<realT> tmp;
625 tmp.resize(m_idx.size());
627 m_devShape.resize(m_idx.size());
628 m_devShape.initialize();
630 for(
int i=0; i < m_nActs; ++i)
633 cuda::cublasTaxpy<realT>(*m_cublasHandle, m_idx.size(), m_devActCommands()+i, m_devInfF() + i*m_idx.size(), 1, m_devShape(), 1);
636 m_devShape.download(tmp.data());
638 _nextShape.setZero();
640 realT * imP = _nextShape.data();
642 for(
size_t n=0; n<m_idx.size(); ++n) imP[m_idx[n]] = tmp[n];
646 _nextShape =
c(0,0)*m_infF.image(0);
650 Eigen::Array<_realT, -1, -1> tmp ;
651 tmp.resize(m_nRows, m_nCols);
654 realT * tmpP = tmp.data();
656 for(
int i=1;i < m_nActs; ++i)
658 realT * imP = m_infF.image(i).data();
659 for(
size_t n=0; n<m_idx.size(); ++n) *(tmpP + m_idx[n]) +=
c(i,0) * *(imP + m_idx[n]);
663 realT * imP = _nextShape.data();
664 for(
size_t n=0; n<m_idx.size(); ++n) *(imP + m_idx[n]) += *(tmpP + m_idx[n]);
674 std::cerr <<
"DM filtering\n";
675 m_filter.filter(_nextShape);
681 _settleTime_counter = 0;
682 _settlingIter = commandV.iterNo;
690 template<
typename _realT>
691 void deformableMirror<_realT>::applyShape(wavefrontT & wf, realT lambda)
700 _shape = _oldShape + (_nextShape-_oldShape)*( (realT) _settleTime_counter+1.0)/( (realT) _settleTime);
702 realT mn = (_shape*m_pupil).sum()/m_pupilSum;
703 _shape = (_shape - mn)*m_pupil;
705 ++_settleTime_counter;
707 if(_settleTime_counter >= _settleTime)
710 _settledIter = _settlingIter;
718 wf.phase += 2*_shape*math::two_pi<realT>()/lambda;
722 #ifdef MXAO_DIAG_LOOPCOUNTS
723 std::cerr <<
"DM " << m_nActs <<
" Shape applied: " << wf.iterNo <<
" " << _settledIter <<
"\n";
727 template<
typename _realT>
728 void deformableMirror<_realT>::setFilter(
int width )
730 int nr = _shape.rows();
731 int nc = _shape.cols();
733 typename wfsImageT<_realT>::imageT filterMask;
735 filterMask.resize( nr, nc );
736 filterMask.setZero();
738 filterMask.block(0,0, width+1, width+1).setConstant(1.0);
739 filterMask.block(0, nc - width, width+1, width).setConstant(1.0);
740 filterMask.block(nr - width, 0, width, width+1).setConstant(1.0);
741 filterMask.block(nr - width, nc - width, width, width).setConstant(1.0);
744 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.
typeT get_curr_time(timespec &tsp)
Get the current system time in seconds.