27 #ifndef __lyotCoronagraph_hpp__
28 #define __lyotCoronagraph_hpp__
36 #include "../ioutils/fits/fitsFile.hpp"
37 #include "../ioutils/fits/fitsUtils.hpp"
39 #include "../improc/eigenImage.hpp"
40 #include "../improc/eigenCube.hpp"
55 template<
typename _realT,
typename _fpmaskFloatT>
69 typedef mx::wfp::imagingArray<std::complex<realT>, fftwAllocator<std::complex<realT> >, 0>
complexFieldT;
72 typedef Eigen::Array< std::complex<fpmaskFloatT>, Eigen::Dynamic, Eigen::Dynamic>
fpMaskT;
75 typedef Eigen::Array< realT, Eigen::Dynamic, Eigen::Dynamic>
imageT;
105 bool m_savePreMaskFocalPlane {
false};
108 bool m_savePreLyotPupilPlane {
false};
163 const std::string & fpmName,
164 const std::string & lyotName
205 const std::string & cname
214 const std::string & cname
219 template<
typename _realT,
typename _fpmaskFloatT>
224 template<
typename _realT,
typename _fpmaskFloatT>
230 template<
typename _realT,
typename _fpmaskFloatT>
235 m_fp.setWavefrontSizePixels(sz);
236 m_focalPlane.resize(sz, sz);
240 template<
typename _realT,
typename _fpmaskFloatT>
248 if(sz % 2 == 1) ++sz;
256 m_focalMask.resize(sz,sz);
257 for(
int i=0; i<sz; ++i)
259 for(
int j=0; j<sz; ++j)
261 if(fpm(i,j) == 1) m_focalMask(i,j) = std::complex<fpmaskFloatT>(trans,0);
262 else m_focalMask(i,j) = std::complex<fpmaskFloatT>(1,0);
273 template<
typename _realT,
typename _fpmaskFloatT>
278 return ff.
read(m_pupilApodizer, apodName);
282 template<
typename _realT,
typename _fpmaskFloatT>
288 if(ff.
read(fpm, fpmName) < 0)
return -1;
292 m_focalMask = fpm.
image(0);
294 else if(fpm.planes()==2)
296 m_focalMask.resize( fpm.rows(), fpm.cols());
298 for(
int r = 0; r < fpm.rows(); ++r)
300 for(
int c = 0;
c < fpm.cols(); ++
c)
302 m_focalMask(r,
c) = fpm.
image(0)(r,
c)*exp( std::complex<fpmaskFloatT>(0, fpm.
image(1)(r,
c)));
308 std::cerr <<
"too many planes in focal mask file\n";
313 m_maskFile = fpmName;
320 template<
typename _realT,
typename _fpmaskFloatT>
325 return ff.
read(m_lyotStop, lyotName);
329 template<
typename _realT,
typename _fpmaskFloatT>
331 const std::string & fpmName,
332 const std::string & lyotName)
334 if(loadApodizer(apodName) < 0)
return -1;
335 if(loadFocalMask(fpmName) < 0)
return -1;
336 if(loadLyotStop(lyotName) < 0)
return -1;
341 template<
typename _realT,
typename _fpmaskFloatT>
346 mxError(
"lyotCoronagraph", MXE_PARAMNOTSET,
"file directory (fileDir) not set.");
350 std::string apodName= m_fileDir +
"/" + cName +
"_apod.fits";
351 std::string fpmName = m_fileDir +
"/" + cName +
"_fpm.fits";
352 std::string lyotName = m_fileDir +
"/" + cName +
"_lyot.fits";
354 return loadCoronagraph(apodName, fpmName, lyotName);
357 template<
typename _realT,
typename _fpmaskFloatT>
360 int sz = m_pupilApodizer.rows();
362 realT w = 0.5*(sz - 1.0);
364 realT xc = 0.5*(pupilPlane.rows() - 1);
365 realT yc = 0.5*(pupilPlane.cols() - 1);
367 for(
int i=0; i<pupilPlane.rows(); ++i)
369 for(
int j=0; j<pupilPlane.cols(); ++j)
371 if(i >= xc-w && i <= xc+w && j >= yc-w && j <= yc+w) pupilPlane( i, j) *= m_pupilApodizer((
int)(i-(xc-w)),(
int)(j-(yc-w)));
372 else pupilPlane(i,j) *= 0;
378 template<
typename _realT,
typename _fpmaskFloatT>
379 void lyotCoronagraph<_realT, _fpmaskFloatT>::applyFocalMask( complexFieldT &focalPlane )
381 int sz = m_focalMask.rows();
383 realT w = 0.5*(sz - 1.0);
385 realT xc = 0.5*(focalPlane.rows() - 1);
386 realT yc = 0.5*(focalPlane.cols() - 1);
388 for(
int i=0; i<sz; ++i)
390 for(
int j=0; j<sz; ++j)
392 focalPlane( xc - w + i, yc - w + j ) *= m_focalMask(i,j);
398 template<
typename _realT,
typename _fpmaskFloatT>
399 void lyotCoronagraph<_realT, _fpmaskFloatT>::applyLyotStop( complexFieldT & lyotPlane )
401 int sz = m_lyotStop.rows();
403 realT w = 0.5*(sz - 1.0);
405 realT xc = 0.5*(lyotPlane.rows() - 1);
406 realT yc = 0.5*(lyotPlane.cols() - 1);
408 for(
int i=0; i< lyotPlane.rows(); ++i)
410 for(
int j=0; j< lyotPlane.cols(); ++j)
412 if(i >= xc-w && i <= xc+w && j >= yc-w && j <= yc+w) lyotPlane( i, j) *= m_lyotStop((
int)(i - (xc-w)),(
int)(j - (yc-w)));
413 else lyotPlane(i,j) = 0;
419 template<
typename _realT,
typename _fpmaskFloatT>
422 applyApodizer( pupilPlane);
424 m_fp.propagatePupilToFocal(m_focalPlane, pupilPlane);
426 if(m_savePreMaskFocalPlane)
428 m_preMaskFocalPlane = m_focalPlane;
431 applyFocalMask( m_focalPlane);
433 m_fp.propagateFocalToPupil(pupilPlane, m_focalPlane);
435 if(m_savePreLyotPupilPlane)
437 m_preLyotPupilPlane = pupilPlane;
440 applyLyotStop( pupilPlane);
445 template<
typename _realT,
typename _fpmaskFloatT>
450 propagate(pupilPlane);
452 m_fp.propagatePupilToFocal(m_focalPlane, pupilPlane);
454 int x0 = 0.5*(m_wfSz-1) - 0.5*(fpIntensity.rows()-1);
455 int y0 = 0.5*(m_wfSz-1) - 0.5*(fpIntensity.cols()-1);
457 extractIntensityImage(fpIntensity,0, fpIntensity.rows(),0,fpIntensity.cols(), m_focalPlane, x0,y0);
461 template<
typename _realT,
typename _fpmaskFloatT>
464 applyApodizer( pupilPlane);
466 m_fp.propagatePupilToFocal(m_focalPlane, pupilPlane);
468 m_fp.propagateFocalToPupil(pupilPlane, m_focalPlane);
470 applyLyotStop( pupilPlane);
475 template<
typename _realT,
typename _fpmaskFloatT>
480 propagateNC(pupilPlane);
482 m_fp.propagatePupilToFocal(m_focalPlane, pupilPlane);
484 int x0 = 0.5*(m_wfSz-1) - 0.5*(fpIntensity.rows()-1);
485 int y0 = 0.5*(m_wfSz-1) - 0.5*(fpIntensity.cols()-1);
487 extractIntensityImage(fpIntensity,0, fpIntensity.rows(),0,fpIntensity.cols(), m_focalPlane, x0,y0);
493 template<
typename _realT,
typename _fpmaskFloatT>
499 const std::string & cname )
503 pupilPlane.resize(m_wfSz, m_wfSz);
504 focalPlane.resize(m_wfSz, m_wfSz);
506 mx::wfp::imagingArray<realT,fftwAllocator<realT>, 0> mask(m_wfSz, m_wfSz);
514 mx::wfp::imagingArray<realT,fftwAllocator<realT>, 0> pupilImage(m_wfSz, m_wfSz);
515 pupilImage.setZero();
517 int gpLLi = 0.5*(m_wfSz-1) - 0.5*(geomPupil.rows()-1);
518 int gpLLj = 0.5*(m_wfSz-1) - 0.5*(geomPupil.cols()-1);
520 int gpURi = gpLLi + geomPupil.rows();
521 int gpURj = gpLLj + geomPupil.cols();
523 for(
int i=0;i<geomPupil.rows();++i)
525 for(
int j=0;j< geomPupil.cols();++j)
527 pupilImage(gpLLi + i, gpLLj + j) = geomPupil(i,j);
531 realT lastLambdaA, LambdaA;
536 for(n=0; n< maxIter; ++n)
540 m_fp.propagatePupilToFocal(focalPlane, pupilPlane);
542 for(
int i=0; i < m_wfSz; ++i)
544 for(
int j=0;j < m_wfSz; ++j)
546 focalPlane(i,j) *= mask(i,j);
550 m_fp.propagateFocalToPupil(pupilPlane, focalPlane);
552 for(
int i=0; i< m_wfSz; ++i)
for(
int j=0;j< m_wfSz; ++j) pupilImage(i,j) = abs(pupilPlane(i,j));
556 for(
int i=0; i< m_wfSz; ++i)
558 for(
int j=0;j< m_wfSz; ++j)
560 if( i >= gpLLi && i < gpURi && j >= gpLLj && j < gpURj)
562 pupilImage(i,j) *= geomPupil(i-gpLLi,j-gpLLj);
563 if(pupilImage(i,j) > LambdaA) LambdaA = pupilImage(i,j);
572 for(
int i=0; i< m_wfSz; ++i)
for(
int j=0;j<m_wfSz; ++j) pupilImage(i,j) /= LambdaA;
574 std::cout << n <<
" " << LambdaA <<
"\n";
575 if( fabs(LambdaA - lastLambdaA) < absTol)
577 std::cout <<
"Converged on absTol.\n";
581 if( fabs((LambdaA - lastLambdaA)/lastLambdaA) < relTol)
583 std::cout <<
"Converged on relTol.\n";
590 std::cout <<
"maxIter reached.\n";
594 lastLambdaA = LambdaA;
596 if(LambdaA > 1) LambdaA = 1;
598 std::cout <<
"LambdaA: = " << LambdaA <<
"\n";
600 realT trans = 1.0 - 1.0/LambdaA;
602 int pupSize = geomPupil.rows();
604 m_pupilApodizer.resize(pupSize, pupSize);
606 extractBlock(m_pupilApodizer, 0, pupSize, 0, pupSize, pupilImage, 0.5*( (pupilImage.rows()-1) - (pupSize-1)), 0.5*( (pupilImage.rows()-1) - (pupSize-1)));
608 makeFocalMask(fpmRadPix, trans, pupSize);
620 m_lyotStop = geomPupil;
625 head.
append(
"", fits::fitsCommentType(),
"----------------------------------------");
626 head.
append(
"", fits::fitsCommentType(),
"lyotCoronagraph optimization Parameters:");
627 head.
append(
"", fits::fitsCommentType(),
"----------------------------------------");
628 head.
append<
int>(
"WFSZ", m_wfSz,
"Size of wavefront used for FFTs (pixels)");
629 head.
append<
realT>(
"FPMRADPX", fpmRadPix,
"input radius of focal plane mask (pixels)");
630 head.
append<
realT>(
"ABSTOL", absTol ,
"input absolute tolerance");
631 head.
append<
realT>(
"RELTOL", relTol ,
"input relative tolerance");
632 head.
append<
int>(
"MAXITER", maxIter ,
"input maximum iterations");
633 head.
append<
int>(
"NITER", n ,
"actual number of iterations");
634 head.
append<std::string>(
"XREASON", reason ,
"reason for convergence");
635 head.
append<
realT>(
"FPMTRANS", trans,
"transmission of FPM");
640 std::string fname =
"coron/" + cname +
"_apod.fits";
642 ff.
write(fname, m_pupilApodizer, head);
644 fname =
"coron/" + cname +
"_fpm.fits";
646 for(
int r=0;r<m_focalMask.rows(); ++r)
648 for(
int c=0;
c< m_focalMask.cols(); ++
c)
650 fpm(r,
c) = m_focalMask(r,
c).real();
654 ff.write(fname, fpm,head);
656 fname =
"coron/" + cname +
"_lyot.fits";
657 ff.write(fname, m_lyotStop, head);
660 template<
typename _realT,
typename _fpmaskFloatT>
667 const std::string & cname )
671 pupilPlane.resize(m_wfSz, m_wfSz);
672 focalPlane.resize(m_wfSz, m_wfSz);
674 mx::wfp::imagingArray<realT,fftwAllocator<realT>, 0> mask(m_wfSz, m_wfSz);
678 mx::wfp::imagingArray<realT,fftwAllocator<realT>, 0> pupilImage(m_wfSz, m_wfSz);
679 pupilImage.setZero();
681 int gpLLi = 0.5*(m_wfSz-1) - 0.5*(geomPupil.rows()-1);
682 int gpLLj = 0.5*(m_wfSz-1) - 0.5*(geomPupil.cols()-1);
684 int gpURi = gpLLi + geomPupil.rows();
685 int gpURj = gpLLj + geomPupil.cols();
687 for(
int i=0;i<geomPupil.rows();++i)
689 for(
int j=0;j< geomPupil.cols();++j)
691 pupilImage(gpLLi + i, gpLLj + j) = geomPupil(i,j);
695 realT lastLambdaA, LambdaA;
700 for(n=0; n< maxIter; ++n)
704 m_fp.propagatePupilToFocal(focalPlane, pupilPlane);
706 for(
int i=0; i < m_wfSz; ++i)
708 for(
int j=0;j < m_wfSz; ++j)
710 focalPlane(i,j) *= mask(i,j)*exp( std::complex<realT>(0, fpmPhase(i,j)));;
714 m_fp.propagateFocalToPupil(pupilPlane, focalPlane);
716 for(
int i=0; i< m_wfSz; ++i)
for(
int j=0;j< m_wfSz; ++j) pupilImage(i,j) = abs(pupilPlane(i,j));
720 for(
int i=0; i< m_wfSz; ++i)
722 for(
int j=0;j< m_wfSz; ++j)
724 if( i >= gpLLi && i < gpURi && j >= gpLLj && j < gpURj)
726 pupilImage(i,j) *= geomPupil(i-gpLLi,j-gpLLj);
727 if(pupilImage(i,j) > LambdaA) LambdaA = pupilImage(i,j);
736 for(
int i=0; i< m_wfSz; ++i)
for(
int j=0;j<m_wfSz; ++j) pupilImage(i,j) /= LambdaA;
738 std::cout << n <<
" " << LambdaA <<
"\n";
739 if( fabs(LambdaA - lastLambdaA) < absTol)
741 std::cout <<
"Converged on absTol.\n";
745 if( fabs((LambdaA - lastLambdaA)/lastLambdaA) < relTol)
747 std::cout <<
"Converged on relTol.\n";
754 std::cout <<
"maxIter reached.\n";
758 lastLambdaA = LambdaA;
760 if(LambdaA > 1) LambdaA = 1;
762 std::cout <<
"LambdaA: = " << LambdaA <<
"\n";
764 realT trans = 1.0 - 1.0/LambdaA;
766 int pupSize = geomPupil.rows();
768 m_pupilApodizer.resize(pupSize, pupSize);
770 extractBlock(m_pupilApodizer, 0, pupSize, 0, pupSize, pupilImage, 0.5*( (pupilImage.rows()-1) - (pupSize-1)), 0.5*( (pupilImage.rows()-1) - (pupSize-1)));
772 makeFocalMask(fpmRadPix, trans, pupSize);
775 m_lyotStop = geomPupil;
780 head.
append(
"", fits::fitsCommentType(),
"----------------------------------------");
781 head.
append(
"", fits::fitsCommentType(),
"lyotCoronagraph optimization Parameters:");
782 head.
append(
"", fits::fitsCommentType(),
"----------------------------------------");
783 head.
append<
int>(
"WFSZ", m_wfSz,
"Size of wavefront used for FFTs (pixels)");
784 head.
append<
realT>(
"FPMRADPX", fpmRadPix,
"input radius of focal plane mask (pixels)");
785 head.
append<
realT>(
"ABSTOL", absTol ,
"input absolute tolerance");
786 head.
append<
realT>(
"RELTOL", relTol ,
"input relative tolerance");
787 head.
append<
int>(
"MAXITER", maxIter ,
"input maximum iterations");
788 head.
append<
int>(
"NITER", n ,
"actual number of iterations");
789 head.
append<std::string>(
"XREASON", reason ,
"reason for convergence");
790 head.
append<
realT>(
"FPMTRANS", trans,
"transmission of FPM");
795 std::string fname =
"coron/" + cname +
"_apod.fits";
797 ff.
write(fname, m_pupilApodizer, head);
799 fname =
"coron/" + cname +
"_fpm.fits";
801 for(
int r=0;r<m_focalMask.rows(); ++r)
803 for(
int c=0;
c< m_focalMask.cols(); ++
c)
805 fpm(r,
c) = m_focalMask(r,
c).real();
809 ff.write(fname, fpm,head);
811 fname =
"coron/" + cname +
"_lyot.fits";
812 ff.write(fname, m_lyotStop, head);
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.
An image cube with an Eigen-like API.
Eigen::Map< Eigen::Array< dataT, Eigen::Dynamic, Eigen::Dynamic > > image(Index n)
Returns a 2D Eigen::Eigen::Map pointed at the specified image.
Declares and defines a class for Fraunhofer propagation of optical wavefronts.
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.
void makeComplexPupil(arrayOutT &complexPupil, const arrayInT &realPupil, int wavefrontSizePixels)
Create a complex pupil plane wavefront from a real amplitude mask.
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.
Declares and defines a class for managing images.
Utilities for modeling image formation.
std::string m_maskFile
Name of file from which mask was loaded.
Eigen::Array< realT, Eigen::Dynamic, Eigen::Dynamic > imageT
The image type.
int loadCoronagraph(const std::string &apodName, const std::string &fpmName, const std::string &lyotName)
Load the components of the coronagraph from FITS files.
lyotCoronagraph()
Default c'tor.
int m_maskSource
0= read from file, 1 = constructed by makeFocalMask, 2 = trans optimized.
int m_wfSz
The linear size of the wavefront in pixels.
int loadApodizer(const std::string &apodName)
Load the apodizer from a FITS file.
Eigen::Array< std::complex< fpmaskFloatT >, Eigen::Dynamic, Eigen::Dynamic > fpMaskT
The focal plane mask type.
int propagate(complexFieldT &pupilPlane)
Propagate the given pupil-plane wavefront through the coronagraph.
mx::wfp::imagingArray< std::complex< realT >, fftwAllocator< std::complex< realT > >, 0 > complexFieldT
The wavefront complex field type.
imageT m_lyotStop
Image containing the lyot stop.
void makeFocalMask(realT rad, fpmaskFloatT trans=0.0, int sz=0.0)
Make the focal plane mask.
int propagateNC(complexFieldT &pupilPlane)
Propagate the given pupil-plane wavefront without the coronagraph.
fpMaskT m_focalMask
The focal plane mask.
fraunhoferPropagator< complexFieldT > m_fp
Fraunhofer propagator.
std::complex< realT > complexT
The complex floating point type.
void optimizeAPLCMC(imageT &geomPupil, realT fpmRadPix, realT relTol, realT absTol, int maxIter, const std::string &cname)
Optimize the pupil amplitude apodization and focal-plane mask complex transmission.
_realT realT
The real floating point type.
realT m_maskTrans
Transmission of mask if it was constructed.
imageT m_pupilApodizer
Image containing the pupil apodization.
int loadFocalMask(const std::string &fpmName)
Load the focal plane mask from a FITS file.
int loadLyotStop(const std::string &lyotName)
Load the Lyot stop from a FITS file.
realT m_maskRad
Radius of mask if it was constructed.
_fpmaskFloatT fpmaskFloatT
The real floating point type for mask calculations.
int wfSz()
Get the wavefront size in pixels.
std::string m_fileDir
The directory where coronagraph files are stored.