8 #ifndef simulatedAOSystem_hpp
9 #define simulatedAOSystem_hpp
14 #include <cuda_runtime.h>
15 #include <cublas_v2.h>
18 #include "../../improc/imagePads.hpp"
19 #include "../../wfp/imagingUtils.hpp"
20 #include "../../wfp/fraunhoferPropagator.hpp"
22 #include "../../ioutils/fits/fitsFile.hpp"
23 #include "../../ioutils/fits/fitsUtils.hpp"
25 #include "../../improc/eigenImage.hpp"
26 #include "../../improc/eigenCube.hpp"
28 #include "../../sys/timeUtils.hpp"
29 #include "../../sigproc/signalWindows.hpp"
31 #include "wavefront.hpp"
32 #include "../aoPaths.hpp"
36 #define BREAD_CRUMB std::cout << "DEBUG: " << __FILE__ << " " << __LINE__ << "\n";
63 template<
typename _realT,
typename _wfsT,
typename _reconT,
typename _filterT,
typename _dmT,
typename _turbSeqT,
typename _coronT>
72 typedef Eigen::Array<realT, Eigen::Dynamic, Eigen::Dynamic>
imageT;
74 typedef wfp::imagingArray<std::complex<realT>, wfp::fftwAllocator<std::complex<realT> >, 0>
complexImageT;
77 typedef _reconT reconT;
78 typedef _filterT filterT;
80 typedef _turbSeqT turbSeqT;
81 typedef _coronT coronT;
84 cublasHandle_t m_cublasHandle;
91 bool m_sfImagePlane {
false};
115 int _loopClosedDelay;
118 std::string _rmsFile;
119 std::ofstream _rmsOut;
122 std::string _ampFile;
144 std::string m_wfFileBase {
"simAOWF"};
148 int m_nWFPerFile {500};
150 int m_currWFFile {0};
159 bool _writeIndFrames;
161 long _saveFrameStart;
163 std::string _psfFileBase;
184 coronT m_coronagraph;
189 std::vector<typename filterT::commandT> _delayedCommands;
191 std::vector<int> _goodCommands;
212 typename dmT::specT & dmSpec,
213 const std::string & wfsName,
214 const std::string & pupilName,
218 void initSim(
typename reconT::specT & reconSpec,
221 const std::string & coronName
248 void runTurbulence();
260 int simStep(
const double & ss );
268 int D(
const realT & nD );
272 int wfPS (
const realT & nwfPS);
278 int wfSz(
const int & nwfSz);
282 bool m_doCoron {
false};
287 double dt_turbulence {0};
290 double dt_dmcomb {0};
295 template<
typename realT,
typename wfsT,
typename reconT,
typename filterT,
typename dmT,
typename turbSeqT,
typename coronT>
300 _loopClosedDelay = 0;
305 _writeIndFrames =
false;
311 m_coronagraph.m_fileDir =
sys::getEnv(
"MX_AO_DATADIR") +
"/" +
"coron/";
316 cublasCreate(&m_cublasHandle);
317 cublasSetPointerMode(m_cublasHandle, CUBLAS_POINTER_MODE_DEVICE);
320 template<
typename realT,
typename wfsT,
typename reconT,
typename filterT,
typename dmT,
typename turbSeqT,
typename coronT>
323 if(m_ampOut.rows() > 0 && _ampFile !=
"")
326 ff.
write(_ampFile+
".fits", m_ampOut);
329 if(_rmsOut.is_open()) _rmsOut.close();
332 if(_psfFileBase !=
"" && _currImage > 0 && _writeIndFrames)
348 ff.
write(fn, _corons);
355 template<
typename realT,
typename wfsT,
typename reconT,
typename filterT,
typename dmT,
typename turbSeqT,
typename coronT>
357 typename dmT::specT & dmSpec,
358 const std::string & wfsName,
359 const std::string & pupilName,
364 _pupilName = pupilName;
371 std::string pupilFile = mx::AO::path::pupil::pupilFile(_pupilName);
373 ff.
read(_pupil, head, pupilFile);
375 m_D = head[
"PUPILD"].Value<
realT>();
376 m_wfPS = head[
"SCALE"].Value<
realT>();
383 turbSeq._pupil = &_pupil;
384 turbSeq.wfPS(m_wfPS);
387 dm.initialize( *
this, dmSpec, _pupilName);
389 wfs.linkSystem(*
this);
397 template<
typename realT,
typename wfsT,
typename reconT,
typename filterT,
typename dmT,
typename turbSeqT,
typename coronT>
401 const std::string & coronName
409 wfs.simStep(m_simStep);
412 filter.initialize(dm.nModes());
414 recon.initialize(*
this, reconSpec);
415 dm.calAmp(recon.calAmp());
419 _commandDelay = commandDelay;
421 _delayedCommands.resize((_commandDelay+1)*5);
422 _goodCommands.resize((_commandDelay+1)*5);
426 m_coronagraph.wfSz(m_wfSz);
427 m_coronagraph.loadCoronagraph(coronName);
478 template<
typename realT,
typename wfsT,
typename reconT,
typename filterT,
typename dmT,
typename turbSeqT,
typename coronT>
484 cpup.resize(m_wfSz, m_wfSz);
486 recon.initializeRMat(dm.nModes(), amp, wfs.detRows(), wfs.detCols());
488 typename filterT::commandT measureVec;
491 currWF.setAmplitude(_pupil);
495 wfs.detector.noNoise(
true);
497 double tO,tF, t0, t1, t_applyMode = 0, t_senseWF = 0, t_calcMeas = 0, t_accum = 0;
499 std::cerr << dm.nModes() <<
"\n";
503 for(
int i=0;i< dm.nModes(); ++i)
507 currWF.setPhase(_pupil*0);
510 if(nmodes>0 && i>= nmodes)
513 wfs.detectorImage.image.setZero();
518 dm.applyMode(currWF, i, s_amp, 0.8e-6);
520 t_applyMode += t1-t0;
525 wfs.senseWavefrontCal(currWF);
535 recon.calcMeasurement(measureVec, wfs.detectorImage);
544 recon.accumulateRMat(i, measureVec, wfs.detectorImage);
552 std::cout << ( (
realT) dm.nModes())/(tF - tO) <<
" Hz\n";
554 std::cout << t_applyMode/dm.nModes() <<
" " << t_senseWF/dm.nModes() <<
" " << t_calcMeas/dm.nModes() <<
" " << t_accum/dm.nModes();
555 std::cout <<
" " << dm.t_mm/dm.nModes() <<
" " << dm.t_sum/dm.nModes() <<
" " <<
"\n";
558 fname = mx::AO::path::sys::cal::rMat(_sysName, dm.name(), _wfsName, _pupilName, dm.basisName(), rmatID,
true);
560 std::cout << fname <<
"\n";
561 recon.saveRMat(fname);
563 fname = mx::AO::path::sys::cal::rImages(_sysName, dm.name(), _wfsName, _pupilName, dm.basisName(), rmatID,
true);
564 recon.saveRImages(fname);
568 template<
typename realT,
typename wfsT,
typename reconT,
typename filterT,
typename dmT,
typename turbSeqT,
typename coronT>
571 return turbSeq.frames();
599 template<
typename realT,
typename wfsT,
typename reconT,
typename filterT,
typename dmT,
typename turbSeqT,
typename coronT>
600 void simulatedAOSystem<realT, wfsT, reconT, filterT, dmT, turbSeqT, coronT>::nextWF(wavefrontT & wf)
603 realT rms_ol, rms_cl;
609 _npix = _pupil.sum();
618 wf.iterNo = _frameCounter;
623 realT mn = (wf.phase * _pupil).sum()/_npix;
626 wf.phase = (wf.phase-mn)*_pupil;
628 if(_pupilMask.rows() == _pupil.rows() && _pupilMask.cols() == _pupil.cols())
630 wf.phase *= _pupilMask;
636 if(_frameCounter % 10 == 0) rms_ol = sqrt( wf.phase.square().sum()/ _npix );
640 typename filterT::commandT measuredAmps, commandAmps;
642 filter.initMeasurements(measuredAmps, commandAmps);
644 if(_frameCounter == 0)
646 for(
size_t i=0; i<_delayedCommands.size();++i)
648 _goodCommands[i] = 0;
655 dm.applyShape(wf, _wfsLambda);
662 newCV = wfs.senseWavefront(wf);
670 recon.reconstruct(measuredAmps, wfs.m_detectorImage);
679 if(m_ampOut.cols() != turbSeq.frames() || m_ampOut.rows() != measuredAmps.measurement.size()+1)
681 if(m_ampOut.cols() != 0)
683 std::cerr <<
"m_ampOut already allocated but cols not frames\n";
687 if(m_ampOut.rows() != 0)
689 std::cerr <<
"m_ampOut already allocated but rows not measurements\n";
693 m_ampOut.resize(measuredAmps.measurement.size()+1, turbSeq.frames());
697 int n = floor(measuredAmps.iterNo);
698 m_ampOut(0,n) = measuredAmps.iterNo;
699 for(
int i=1;i<measuredAmps.measurement.size()+1; ++i)
701 m_ampOut(i,n) = measuredAmps.measurement[i-1];
707 int nAmps = ( _frameCounter % _delayedCommands.size() );
709 _delayedCommands[nAmps].measurement = measuredAmps.measurement;
710 _delayedCommands[nAmps].iterNo = measuredAmps.iterNo;
712 _goodCommands[nAmps] = 1;
716 int nAmps = ( _frameCounter % _delayedCommands.size() );
717 _goodCommands[nAmps] = 0;
721 int _currCommand = ( _frameCounter % _delayedCommands.size() ) - _commandDelay;
722 if(_currCommand < 0) _currCommand += _delayedCommands.size();
724 if(_goodCommands[_currCommand])
728 filter.filterCommands(commandAmps, _delayedCommands[_currCommand], _frameCounter);
733 dm.setShape(commandAmps);
741 int nAmps = ( _frameCounter % _delayedCommands.size() );
742 _goodCommands[nAmps] = 0;
747 if(_postMask.rows() != _pupil.rows())
754 if(_frameCounter % 10 == 0)
756 mn = (wf.phase * _pupil).sum()/_npix;
757 rms_cl = sqrt( (wf.phase-mn).square().sum()/ _postMask.sum() );
758 std::cout << _frameCounter <<
" WFE: " << rms_ol <<
" " << rms_cl <<
" [rad rms phase]\n";
763 wfs.filter().filter(wf.phase);
770 if(! _rmsOut.is_open() )
772 _rmsOut.open(_rmsFile);
773 _rmsOut <<
"#open-loop-wfe closed-loop-wfe [rad rms phase]\n";
775 _rmsOut << rms_ol <<
" " << rms_cl << std::endl;
780 if( m_writeWavefronts )
782 if( m_wfPhase.rows() != wf.phase.rows() || m_wfPhase.cols() != wf.phase.cols() || m_wfPhase.planes() != m_nWFPerFile ||
783 m_wfAmp.rows() != wf.amplitude.rows() || m_wfAmp.cols() != wf.amplitude.cols() || m_wfAmp.planes() != m_nWFPerFile )
785 m_wfPhase.resize( wf.phase.rows(), wf.phase.cols(), m_nWFPerFile);
786 m_wfAmp.resize( wf.amplitude.rows(), wf.amplitude.cols(), m_nWFPerFile);
791 m_wfPhase.image(m_currWF) = wf.phase;
792 m_wfAmp.image(m_currWF) = wf.amplitude;
796 if( m_currWF >= m_nWFPerFile )
798 std::cerr <<
"Write to WF file here . . . \n";
802 std::string fn = m_wfFileBase +
"_phase_" + ioutils::convertToString<int,5,'0'>(m_currWFFile) +
".fits";
803 ff.
write(fn, m_wfPhase);
805 fn = m_wfFileBase +
"_amp_" + ioutils::convertToString<int,5,'0'>(m_currWFFile) +
".fits";
816 if(_psfFileBase !=
"" && _frameCounter > _saveFrameStart)
818 if(_psfOut.rows() == 0 || (_psfs.planes() == 0 && _writeIndFrames))
820 if(m_saveSz <= 0) m_saveSz = m_wfSz;
822 if(_writeIndFrames) _psfs.resize(m_saveSz, m_saveSz, _nPerFile);
823 _psfOut.resize(m_saveSz, m_saveSz);
826 _realFocal.resize(m_saveSz, m_saveSz);
830 if(_writeIndFrames) _corons.resize(m_saveSz, m_saveSz, _nPerFile);
831 _coronOut.resize(m_saveSz, m_saveSz);
834 _realFocalCoron.resize(m_saveSz, m_saveSz);
843 wf.getWavefront(_complexPupilCoron, m_wfSz);
845 m_coronagraph.propagate(_realFocalCoron, _complexPupilCoron);
847 if(_writeIndFrames) _corons.image(_currImage) = _realFocalCoron;
849 _coronOut += _realFocalCoron;
853 wf.getWavefront(_complexPupil, m_wfSz);
855 m_coronagraph.propagateNC(_realFocal, _complexPupil);
857 if(_writeIndFrames) _psfs.image(_currImage) = _realFocal;
859 _psfOut += _realFocal;
870 if(_currImage >= _nPerFile && _writeIndFrames)
886 ff.
write(fn, _corons);
899 template<
typename realT,
typename wfsT,
typename reconT,
typename filterT,
typename dmT,
typename turbSeqT,
typename coronT>
900 void simulatedAOSystem<realT, wfsT, reconT, filterT, dmT, turbSeqT, coronT>::runTurbulence()
906 if(m_coronagraph.wfSz() != m_wfSz)
908 std::cerr <<
"doCoron is true, but coronagraph not loaded or wavefront sizes don't match.\n";
909 std::cerr <<
"Continuing . . .\n";
914 _wfsLambda = wfs.lambda();
917 for(
size_t i=0;i<turbSeq.frames();++i)
924 turbSeq._loopClosed =
true;
928 if(i == (
size_t) _loopClosedDelay) _loopClosed =
true;
942 if(_psfFileBase !=
"")
944 fits::fitsFile<realT> ff;
945 std::string fn = _psfFileBase +
"_psf.fits";
947 ff.write(fn, _psfOut);
952 fn = _psfFileBase +
"_coron.fits";
953 ff.write(fn, _coronOut);
959 std::cout <<
"Timing: \n";
960 std::cout <<
" Total Time: " << dt_total <<
" sec / " << turbSeq.frames()/dt_total <<
" fps\n";
961 std::cout <<
" Turbulence: " << dt_turbulence <<
" sec / " << turbSeq.frames()/dt_turbulence <<
" fps / " << dt_turbulence/dt_total <<
"%\n";
962 std::cout <<
" WFS: " << dt_wfs <<
" sec / " << turbSeq.frames()/dt_wfs <<
" fps / " << dt_wfs/dt_total <<
"%\n";
963 std::cout <<
" Recon: " << dt_recon <<
" sec / " << turbSeq.frames()/dt_recon <<
" fps / " << dt_recon/dt_total <<
"%\n";
964 std::cout <<
" dmcomb: " << dt_dmcomb <<
" sec / " << turbSeq.frames()/dt_dmcomb <<
" fps / " << dt_dmcomb/dt_total <<
"%\n";
969 template<
typename realT,
typename wfsT,
typename reconT,
typename filterT,
typename dmT,
typename turbSeqT,
typename coronT>
977 template<
typename realT,
typename wfsT,
typename reconT,
typename filterT,
typename dmT,
typename turbSeqT,
typename coronT>
983 template<
typename realT,
typename wfsT,
typename reconT,
typename filterT,
typename dmT,
typename turbSeqT,
typename coronT>
991 template<
typename realT,
typename wfsT,
typename reconT,
typename filterT,
typename dmT,
typename turbSeqT,
typename coronT>
992 realT simulatedAOSystem<realT, wfsT, reconT, filterT, dmT, turbSeqT, coronT>::D()
997 template<
typename realT,
typename wfsT,
typename reconT,
typename filterT,
typename dmT,
typename turbSeqT,
typename coronT>
998 int simulatedAOSystem<realT, wfsT, reconT, filterT, dmT, turbSeqT, coronT>::wfPS (
const realT & nwfPS)
1005 template<
typename realT,
typename wfsT,
typename reconT,
typename filterT,
typename dmT,
typename turbSeqT,
typename coronT>
1006 realT simulatedAOSystem<realT, wfsT, reconT, filterT, dmT, turbSeqT, coronT>::wfPS()
1011 template<
typename realT,
typename wfsT,
typename reconT,
typename filterT,
typename dmT,
typename turbSeqT,
typename coronT>
1012 int simulatedAOSystem<realT, wfsT, reconT, filterT, dmT, turbSeqT, coronT>::Dpix()
1014 return (
int)(m_D/m_wfPS +std::numeric_limits<realT>::epsilon());
1017 template<
typename realT,
typename wfsT,
typename reconT,
typename filterT,
typename dmT,
typename turbSeqT,
typename coronT>
1018 int simulatedAOSystem<realT, wfsT, reconT, filterT, dmT, turbSeqT, coronT>::wfSz(
const int & nwfSz)
1025 template<
typename realT,
typename wfsT,
typename reconT,
typename filterT,
typename dmT,
typename turbSeqT,
typename coronT>
1026 int simulatedAOSystem<realT, wfsT, reconT, filterT, dmT, turbSeqT, coronT>::wfSz()
int initSystem(const std::string &sysName, typename dmT::specT &dmSpec, const std::string &wfsName, const std::string &pupilName, const int &wfSz)
Initialize the system.
std::string _wfsName
The WFS name for use in the mx::AO::path.
std::string _pupilName
The pupil name for use in the mx::AO::path.
~simulatedAOSystem()
Destructor.
_realT realT
The floating point type used for all calculations.
realT m_simStep
The simulation step size in seconds.
Eigen::Array< realT, Eigen::Dynamic, Eigen::Dynamic > imageT
The real image type.
imageT _pupilMask
A pupil mask which is applied once at the beginning of propagation. Could be apodized and/or differen...
std::string _sysName
The system name for use in mx::AO::path.
imageT _pupil
The system pupil. This is generally a binary mask and will be applied at various points in the propag...
double simStep()
Get the simulation step size.
void takeResponseMatrix(realT amp, std::string rmatName, int nmodes=0)
Measure the system response matrix.
simulatedAOSystem()
Default c'tor.
wfp::imagingArray< std::complex< realT >, wfp::fftwAllocator< std::complex< realT > >, 0 > complexImageT
The complex image type.
mx::AO::sim::wavefront< realT > wavefrontT
The wavefront type.
Class to manage interactions with a FITS file.
int write(const dataT *im, int d1, int d2, int d3, fitsHeader *head)
Write the contents of a raw array to the FITS file.
int read(dataT *data)
Read the contents of the FITS file into an array.
Eigen::Array< scalarT, -1, -1 > eigenImage
Definition of the eigenImage type, which is an alias for Eigen::Array.
std::string convertToString(const typeT &value, int precision=0)
Convert a numerical value to a string.
std::string getEnv(const std::string &estr)
Return the value of an environment variable.
typeT get_curr_time(timespec &tsp)
Get the current system time in seconds.
Structure containing the phase and amplitude of a wavefront