27#ifndef __lyotCoronagraph_hpp__
28#define __lyotCoronagraph_hpp__
57template <
typename _realT,
typename _fpmaskFloatT>
71 typedef mx::wfp::imagingArray<std::complex<realT>, fftwAllocator<std::complex<realT>>, 0>
complexFieldT;
74 typedef Eigen::Array<std::complex<fpmaskFloatT>, Eigen::Dynamic, Eigen::Dynamic>
fpMaskT;
77 typedef Eigen::Array<realT, Eigen::Dynamic, Eigen::Dynamic>
imageT;
103 bool m_savePreMaskFocalPlane{
false };
106 bool m_savePreLyotPupilPlane{
false };
143 const std::string &fpmName );
159 const std::string &fpmName,
160 const std::string &lyotName
213 const std::string &cname
223 const std::string &cname
227template <
typename _realT,
typename _fpmaskFloatT>
232template <
typename _realT,
typename _fpmaskFloatT>
238template <
typename _realT,
typename _fpmaskFloatT>
243 m_fp.setWavefrontSizePixels( sz );
244 m_focalPlane.resize( sz, sz );
247template <
typename _realT,
typename _fpmaskFloatT>
263 for(
int i = 0; i < sz; ++i )
265 for(
int j = 0; j < sz; ++j )
267 if( fpm( i, j ) == 1 )
268 m_focalMask( i, j ) = std::complex<fpmaskFloatT>( trans, 0 );
270 m_focalMask( i, j ) = std::complex<fpmaskFloatT>( 1, 0 );
280template <
typename _realT,
typename _fpmaskFloatT>
291template <
typename _realT,
typename _fpmaskFloatT>
297 if( !!ff.
read( fpm, fpmName ) )
300 if( fpm.planes() == 1 )
304 else if( fpm.planes() == 2 )
308 for(
int r = 0; r < fpm.rows(); ++r )
310 for(
int c = 0; c < fpm.cols(); ++c )
313 fpm.
image( 0 )( r, c ) * exp( std::complex<fpmaskFloatT>( 0, fpm.
image( 1 )( r, c ) ) );
319 std::cerr <<
"too many planes in focal mask file\n";
331template <
typename _realT,
typename _fpmaskFloatT>
342template <
typename _realT,
typename _fpmaskFloatT>
344 const std::string &fpmName,
345 const std::string &lyotName )
357template <
typename _realT,
typename _fpmaskFloatT>
366 std::string apodName =
m_fileDir +
"/" + cName +
"_apod.fits";
367 std::string fpmName =
m_fileDir +
"/" + cName +
"_fpm.fits";
368 std::string lyotName =
m_fileDir +
"/" + cName +
"_lyot.fits";
373template <
typename _realT,
typename _fpmaskFloatT>
374void lyotCoronagraph<_realT, _fpmaskFloatT>::applyApodizer( complexFieldT &pupilPlane )
376 int sz = m_pupilApodizer.rows();
378 realT w = 0.5 * ( sz - 1.0 );
380 realT xc = 0.5 * ( pupilPlane.rows() - 1 );
381 realT yc = 0.5 * ( pupilPlane.cols() - 1 );
383 for(
int i = 0; i < pupilPlane.rows(); ++i )
385 for(
int j = 0; j < pupilPlane.cols(); ++j )
387 if( i >= xc - w && i <= xc + w && j >= yc - w && j <= yc + w )
388 pupilPlane( i, j ) *= m_pupilApodizer( (
int)( i - ( xc - w ) ), (
int)( j - ( yc - w ) ) );
390 pupilPlane( i, j ) *= 0;
395template <
typename _realT,
typename _fpmaskFloatT>
396void lyotCoronagraph<_realT, _fpmaskFloatT>::applyFocalMask( complexFieldT &focalPlane )
398 int sz = m_focalMask.rows();
400 realT w = 0.5 * ( sz - 1.0 );
402 realT xc = 0.5 * ( focalPlane.rows() - 1 );
403 realT yc = 0.5 * ( focalPlane.cols() - 1 );
405 for(
int i = 0; i < sz; ++i )
407 for(
int j = 0; j < sz; ++j )
409 focalPlane( xc - w + i, yc - w + j ) *= m_focalMask( i, j );
414template <
typename _realT,
typename _fpmaskFloatT>
415void lyotCoronagraph<_realT, _fpmaskFloatT>::applyLyotStop( complexFieldT &lyotPlane )
417 int sz = m_lyotStop.rows();
419 realT w = 0.5 * ( sz - 1.0 );
421 realT xc = 0.5 * ( lyotPlane.rows() - 1 );
422 realT yc = 0.5 * ( lyotPlane.cols() - 1 );
424 for(
int i = 0; i < lyotPlane.rows(); ++i )
426 for(
int j = 0; j < lyotPlane.cols(); ++j )
428 if( i >= xc - w && i <= xc + w && j >= yc - w && j <= yc + w )
429 lyotPlane( i, j ) *= m_lyotStop( (
int)( i - ( xc - w ) ), (
int)( j - ( yc - w ) ) );
431 lyotPlane( i, j ) = 0;
436template <
typename _realT,
typename _fpmaskFloatT>
439 applyApodizer( pupilPlane );
441 m_fp.propagatePupilToFocal( m_focalPlane, pupilPlane );
443 if( m_savePreMaskFocalPlane )
445 m_preMaskFocalPlane = m_focalPlane;
448 applyFocalMask( m_focalPlane );
450 m_fp.propagateFocalToPupil( pupilPlane, m_focalPlane );
452 if( m_savePreLyotPupilPlane )
454 m_preLyotPupilPlane = pupilPlane;
457 applyLyotStop( pupilPlane );
462template <
typename _realT,
typename _fpmaskFloatT>
467 m_fp.propagatePupilToFocal( m_focalPlane, pupilPlane );
469 int x0 = 0.5 * (
m_wfSz - 1 ) - 0.5 * ( fpIntensity.rows() - 1 );
470 int y0 = 0.5 * (
m_wfSz - 1 ) - 0.5 * ( fpIntensity.cols() - 1 );
472 extractIntensityImage( fpIntensity, 0, fpIntensity.rows(), 0, fpIntensity.cols(), m_focalPlane, x0, y0 );
476template <
typename _realT,
typename _fpmaskFloatT>
479 applyApodizer( pupilPlane );
481 m_fp.propagatePupilToFocal( m_focalPlane, pupilPlane );
483 m_fp.propagateFocalToPupil( pupilPlane, m_focalPlane );
485 applyLyotStop( pupilPlane );
490template <
typename _realT,
typename _fpmaskFloatT>
495 m_fp.propagatePupilToFocal( m_focalPlane, pupilPlane );
497 int x0 = 0.5 * (
m_wfSz - 1 ) - 0.5 * ( fpIntensity.rows() - 1 );
498 int y0 = 0.5 * (
m_wfSz - 1 ) - 0.5 * ( fpIntensity.cols() - 1 );
500 extractIntensityImage( fpIntensity, 0, fpIntensity.rows(), 0, fpIntensity.cols(), m_focalPlane, x0, y0 );
505template <
typename _realT,
typename _fpmaskFloatT>
507 imageT &geomPupil,
realT fpmRadPix,
realT relTol,
realT absTol,
int maxIter,
const std::string &cname )
514 mx::wfp::imagingArray<realT, fftwAllocator<realT>, 0> mask(
m_wfSz,
m_wfSz );
522 mx::wfp::imagingArray<realT, fftwAllocator<realT>, 0> pupilImage(
m_wfSz,
m_wfSz );
523 pupilImage.setZero();
525 int gpLLi = 0.5 * (
m_wfSz - 1 ) - 0.5 * ( geomPupil.rows() - 1 );
526 int gpLLj = 0.5 * (
m_wfSz - 1 ) - 0.5 * ( geomPupil.cols() - 1 );
528 int gpURi = gpLLi + geomPupil.rows();
529 int gpURj = gpLLj + geomPupil.cols();
531 for(
int i = 0; i < geomPupil.rows(); ++i )
533 for(
int j = 0; j < geomPupil.cols(); ++j )
535 pupilImage( gpLLi + i, gpLLj + j ) = geomPupil( i, j );
539 realT lastLambdaA, LambdaA;
544 for( n = 0; n < maxIter; ++n )
548 m_fp.propagatePupilToFocal( focalPlane, pupilPlane );
550 for(
int i = 0; i <
m_wfSz; ++i )
552 for(
int j = 0; j <
m_wfSz; ++j )
554 focalPlane( i, j ) *= mask( i, j );
558 m_fp.propagateFocalToPupil( pupilPlane, focalPlane );
560 for(
int i = 0; i <
m_wfSz; ++i )
561 for(
int j = 0; j <
m_wfSz; ++j )
562 pupilImage( i, j ) = abs( pupilPlane( i, j ) );
565 for(
int i = 0; i <
m_wfSz; ++i )
567 for(
int j = 0; j <
m_wfSz; ++j )
569 if( i >= gpLLi && i < gpURi && j >= gpLLj && j < gpURj )
571 pupilImage( i, j ) *= geomPupil( i - gpLLi, j - gpLLj );
572 if( pupilImage( i, j ) > LambdaA )
573 LambdaA = pupilImage( i, j );
577 pupilImage( i, j ) = 0;
582 for(
int i = 0; i <
m_wfSz; ++i )
583 for(
int j = 0; j <
m_wfSz; ++j )
584 pupilImage( i, j ) /= LambdaA;
586 std::cout << n <<
" " << LambdaA <<
"\n";
587 if( fabs( LambdaA - lastLambdaA ) < absTol )
589 std::cout <<
"Converged on absTol.\n";
593 if( fabs( ( LambdaA - lastLambdaA ) / lastLambdaA ) < relTol )
595 std::cout <<
"Converged on relTol.\n";
600 if( n == maxIter - 1 )
602 std::cout <<
"maxIter reached.\n";
606 lastLambdaA = LambdaA;
611 std::cout <<
"LambdaA: = " << LambdaA <<
"\n";
613 realT trans = 1.0 - 1.0 / LambdaA;
615 int pupSize = geomPupil.rows();
625 0.5 * ( ( pupilImage.rows() - 1 ) - ( pupSize - 1 ) ),
626 0.5 * ( ( pupilImage.rows() - 1 ) - ( pupSize - 1 ) ) );
644 head.
append(
"", fits::fitsCommentType(),
"----------------------------------------" );
645 head.
append(
"", fits::fitsCommentType(),
"lyotCoronagraph optimization Parameters:" );
646 head.
append(
"", fits::fitsCommentType(),
"----------------------------------------" );
647 head.
append<
int>(
"WFSZ",
m_wfSz,
"Size of wavefront used for FFTs (pixels)" );
648 head.
append<
realT>(
"FPMRADPX", fpmRadPix,
"input radius of focal plane mask (pixels)" );
649 head.
append<
realT>(
"ABSTOL", absTol,
"input absolute tolerance" );
650 head.
append<
realT>(
"RELTOL", relTol,
"input relative tolerance" );
651 head.
append<
int>(
"MAXITER", maxIter,
"input maximum iterations" );
652 head.
append<
int>(
"NITER", n,
"actual number of iterations" );
653 head.
append<std::string>(
"XREASON", reason,
"reason for convergence" );
654 head.
append<
realT>(
"FPMTRANS", trans,
"transmission of FPM" );
658 std::string fname =
"coron/" + cname +
"_apod.fits";
662 fname =
"coron/" + cname +
"_fpm.fits";
672 ff.write( fname, fpm, head );
674 fname =
"coron/" + cname +
"_lyot.fits";
678template <
typename _realT,
typename _fpmaskFloatT>
685 const std::string &cname )
692 mx::wfp::imagingArray<realT, fftwAllocator<realT>, 0> mask(
m_wfSz,
m_wfSz );
696 mx::wfp::imagingArray<realT, fftwAllocator<realT>, 0> pupilImage(
m_wfSz,
m_wfSz );
697 pupilImage.setZero();
699 int gpLLi = 0.5 * (
m_wfSz - 1 ) - 0.5 * ( geomPupil.rows() - 1 );
700 int gpLLj = 0.5 * (
m_wfSz - 1 ) - 0.5 * ( geomPupil.cols() - 1 );
702 int gpURi = gpLLi + geomPupil.rows();
703 int gpURj = gpLLj + geomPupil.cols();
705 for(
int i = 0; i < geomPupil.rows(); ++i )
707 for(
int j = 0; j < geomPupil.cols(); ++j )
709 pupilImage( gpLLi + i, gpLLj + j ) = geomPupil( i, j );
713 realT lastLambdaA, LambdaA;
718 for( n = 0; n < maxIter; ++n )
722 m_fp.propagatePupilToFocal( focalPlane, pupilPlane );
724 for(
int i = 0; i <
m_wfSz; ++i )
726 for(
int j = 0; j <
m_wfSz; ++j )
728 focalPlane( i, j ) *= mask( i, j ) * exp( std::complex<realT>( 0, fpmPhase( i, j ) ) );
733 m_fp.propagateFocalToPupil( pupilPlane, focalPlane );
735 for(
int i = 0; i <
m_wfSz; ++i )
736 for(
int j = 0; j <
m_wfSz; ++j )
737 pupilImage( i, j ) = abs( pupilPlane( i, j ) );
740 for(
int i = 0; i <
m_wfSz; ++i )
742 for(
int j = 0; j <
m_wfSz; ++j )
744 if( i >= gpLLi && i < gpURi && j >= gpLLj && j < gpURj )
746 pupilImage( i, j ) *= geomPupil( i - gpLLi, j - gpLLj );
747 if( pupilImage( i, j ) > LambdaA )
748 LambdaA = pupilImage( i, j );
752 pupilImage( i, j ) = 0;
757 for(
int i = 0; i <
m_wfSz; ++i )
758 for(
int j = 0; j <
m_wfSz; ++j )
759 pupilImage( i, j ) /= LambdaA;
761 std::cout << n <<
" " << LambdaA <<
"\n";
762 if( fabs( LambdaA - lastLambdaA ) < absTol )
764 std::cout <<
"Converged on absTol.\n";
768 if( fabs( ( LambdaA - lastLambdaA ) / lastLambdaA ) < relTol )
770 std::cout <<
"Converged on relTol.\n";
775 if( n == maxIter - 1 )
777 std::cout <<
"maxIter reached.\n";
781 lastLambdaA = LambdaA;
786 std::cout <<
"LambdaA: = " << LambdaA <<
"\n";
788 realT trans = 1.0 - 1.0 / LambdaA;
790 int pupSize = geomPupil.rows();
800 0.5 * ( ( pupilImage.rows() - 1 ) - ( pupSize - 1 ) ),
801 0.5 * ( ( pupilImage.rows() - 1 ) - ( pupSize - 1 ) ) );
810 head.
append(
"", fits::fitsCommentType(),
"----------------------------------------" );
811 head.
append(
"", fits::fitsCommentType(),
"lyotCoronagraph optimization Parameters:" );
812 head.
append(
"", fits::fitsCommentType(),
"----------------------------------------" );
813 head.
append<
int>(
"WFSZ",
m_wfSz,
"Size of wavefront used for FFTs (pixels)" );
814 head.
append<
realT>(
"FPMRADPX", fpmRadPix,
"input radius of focal plane mask (pixels)" );
815 head.
append<
realT>(
"ABSTOL", absTol,
"input absolute tolerance" );
816 head.
append<
realT>(
"RELTOL", relTol,
"input relative tolerance" );
817 head.
append<
int>(
"MAXITER", maxIter,
"input maximum iterations" );
818 head.
append<
int>(
"NITER", n,
"actual number of iterations" );
819 head.
append<std::string>(
"XREASON", reason,
"reason for convergence" );
820 head.
append<
realT>(
"FPMTRANS", trans,
"transmission of FPM" );
824 std::string fname =
"coron/" + cname +
"_apod.fits";
828 fname =
"coron/" + cname +
"_fpm.fits";
838 ff.write( fname, fpm, head );
840 fname =
"coron/" + cname +
"_lyot.fits";
Class to manage interactions with a FITS file.
error_t read(dataT *data)
Read the contents of the FITS file into an array.
error_t write(const dataT *im, int d1, int d2, int d3, fitsHeader< verboseT > *head)
Write the contents of a raw array to the FITS file.
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.
Class to perform Fraunhofer propagation between pupil and focal planes.
An image cube with an Eigen API.
Tools for using the eigen library for image processing.
Declares and defines a class to work with a FITS file.
Declares and defines utilities to work with FITS files.
Declares and defines a class for Fraunhofer propagation of optical wavefronts.
Eigen::Array< scalarT, -1, -1 > eigenImage
Definition of the eigenImage type, which is an alias for Eigen::Array.
#define mxError(esrc, ecode, expl)
This reports an mxlib specific error.
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.
#define MXE_PARAMNOTSET
A parameter was not set.
Declares and defines a class for managing images.
Utilities for modeling image formation.
void extractBlock(imageT1 &dest, int imX0, int imXsz, int imY0, int imYsz, imageT2 &src, int wfX0, int wfY0)
Extract a block from one image and insert it into a second.
Old version. Deprecated. Declares and defines the mxlib error reporting system.
std::string m_maskFile
Name of file from which mask was loaded.
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.
Eigen::Array< realT, Eigen::Dynamic, Eigen::Dynamic > imageT
The image type.
int m_wfSz
The linear size of the wavefront in pixels.
int loadApodizer(const std::string &apodName)
Load the apodizer from a FITS file.
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.
Eigen::Array< std::complex< fpmaskFloatT >, Eigen::Dynamic, Eigen::Dynamic > fpMaskT
The focal plane mask type.
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.