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" 
   55template <
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;
 
  101    bool m_savePreMaskFocalPlane{ 
false };
 
  104    bool m_savePreLyotPupilPlane{ 
false };
 
  141        const std::string &fpmName  );
 
  157                     const std::string &fpmName, 
 
  158                     const std::string &lyotName 
 
  211                    const std::string &cname 
 
  221                    const std::string &cname 
 
 
  225template <
typename _realT, 
typename _fpmaskFloatT>
 
  230template <
typename _realT, 
typename _fpmaskFloatT>
 
  236template <
typename _realT, 
typename _fpmaskFloatT>
 
  241    m_fp.setWavefrontSizePixels( sz );
 
  242    m_focalPlane.resize( sz, sz );
 
 
  245template <
typename _realT, 
typename _fpmaskFloatT>
 
  260    m_focalMask.resize( sz, sz );
 
  261    for( 
int i = 0; i < sz; ++i )
 
  263        for( 
int j = 0; j < sz; ++j )
 
  265            if( fpm( i, j ) == 1 )
 
  266                m_focalMask( i, j ) = std::complex<fpmaskFloatT>( trans, 0 );
 
  268                m_focalMask( i, j ) = std::complex<fpmaskFloatT>( 1, 0 );
 
 
  278template <
typename _realT, 
typename _fpmaskFloatT>
 
  283    return ff.
read( m_pupilApodizer, apodName );
 
 
  286template <
typename _realT, 
typename _fpmaskFloatT>
 
  292    if( ff.
read( fpm, fpmName ) < 0 )
 
  295    if( fpm.planes() == 1 )
 
  297        m_focalMask = fpm.
image( 0 );
 
  299    else if( fpm.planes() == 2 )
 
  301        m_focalMask.resize( fpm.rows(), fpm.cols() );
 
  303        for( 
int r = 0; r < fpm.rows(); ++r )
 
  305            for( 
int c = 0; c < fpm.cols(); ++c )
 
  307                m_focalMask( r, c ) =
 
  308                    fpm.
image( 0 )( r, c ) * exp( std::complex<fpmaskFloatT>( 0, fpm.
image( 1 )( r, c ) ) );
 
  314        std::cerr << 
"too many planes in focal mask file\n";
 
  319    m_maskFile = fpmName;
 
 
  326template <
typename _realT, 
typename _fpmaskFloatT>
 
  331    return ff.
read( m_lyotStop, lyotName );
 
 
  334template <
typename _realT, 
typename _fpmaskFloatT>
 
  336                                                             const std::string &fpmName,
 
  337                                                             const std::string &lyotName )
 
  339    if( loadApodizer( apodName ) < 0 )
 
  341    if( loadFocalMask( fpmName ) < 0 )
 
  343    if( loadLyotStop( lyotName ) < 0 )
 
 
  349template <
typename _realT, 
typename _fpmaskFloatT>
 
  352    if( m_fileDir == 
"" )
 
  358    std::string apodName = m_fileDir + 
"/" + cName + 
"_apod.fits";
 
  359    std::string fpmName = m_fileDir + 
"/" + cName + 
"_fpm.fits";
 
  360    std::string lyotName = m_fileDir + 
"/" + cName + 
"_lyot.fits";
 
  362    return loadCoronagraph( apodName, fpmName, lyotName );
 
 
  365template <
typename _realT, 
typename _fpmaskFloatT>
 
  368    int sz = m_pupilApodizer.rows();
 
  370    realT w = 0.5 * ( sz - 1.0 );
 
  372    realT xc = 0.5 * ( pupilPlane.rows() - 1 );
 
  373    realT yc = 0.5 * ( pupilPlane.cols() - 1 );
 
  375    for( 
int i = 0; i < pupilPlane.rows(); ++i )
 
  377        for( 
int j = 0; j < pupilPlane.cols(); ++j )
 
  379            if( i >= xc - w && i <= xc + w && j >= yc - w && j <= yc + w )
 
  380                pupilPlane( i, j ) *= m_pupilApodizer( (
int)( i - ( xc - w ) ), (
int)( j - ( yc - w ) ) );
 
  382                pupilPlane( i, j ) *= 0;
 
  387template <
typename _realT, 
typename _fpmaskFloatT>
 
  388void lyotCoronagraph<_realT, _fpmaskFloatT>::applyFocalMask( complexFieldT &focalPlane )
 
  390    int sz = m_focalMask.rows();
 
  392    realT w = 0.5 * ( sz - 1.0 );
 
  394    realT xc = 0.5 * ( focalPlane.rows() - 1 );
 
  395    realT yc = 0.5 * ( focalPlane.cols() - 1 );
 
  397    for( 
int i = 0; i < sz; ++i )
 
  399        for( 
int j = 0; j < sz; ++j )
 
  401            focalPlane( xc - w + i, yc - w + j ) *= m_focalMask( i, j );
 
  406template <
typename _realT, 
typename _fpmaskFloatT>
 
  407void lyotCoronagraph<_realT, _fpmaskFloatT>::applyLyotStop( complexFieldT &lyotPlane )
 
  409    int sz = m_lyotStop.rows();
 
  411    realT w = 0.5 * ( sz - 1.0 );
 
  413    realT xc = 0.5 * ( lyotPlane.rows() - 1 );
 
  414    realT yc = 0.5 * ( lyotPlane.cols() - 1 );
 
  416    for( 
int i = 0; i < lyotPlane.rows(); ++i )
 
  418        for( 
int j = 0; j < lyotPlane.cols(); ++j )
 
  420            if( i >= xc - w && i <= xc + w && j >= yc - w && j <= yc + w )
 
  421                lyotPlane( i, j ) *= m_lyotStop( (
int)( i - ( xc - w ) ), (
int)( j - ( yc - w ) ) );
 
  423                lyotPlane( i, j ) = 0;
 
  428template <
typename _realT, 
typename _fpmaskFloatT>
 
  431    applyApodizer( pupilPlane );
 
  433    m_fp.propagatePupilToFocal( m_focalPlane, pupilPlane );
 
  435    if( m_savePreMaskFocalPlane )
 
  437        m_preMaskFocalPlane = m_focalPlane;
 
  440    applyFocalMask( m_focalPlane );
 
  442    m_fp.propagateFocalToPupil( pupilPlane, m_focalPlane );
 
  444    if( m_savePreLyotPupilPlane )
 
  446        m_preLyotPupilPlane = pupilPlane;
 
  449    applyLyotStop( pupilPlane );
 
 
  454template <
typename _realT, 
typename _fpmaskFloatT>
 
  457    propagate( pupilPlane );
 
  459    m_fp.propagatePupilToFocal( m_focalPlane, pupilPlane );
 
  461    int x0 = 0.5 * ( m_wfSz - 1 ) - 0.5 * ( fpIntensity.rows() - 1 );
 
  462    int y0 = 0.5 * ( m_wfSz - 1 ) - 0.5 * ( fpIntensity.cols() - 1 );
 
  464    extractIntensityImage( fpIntensity, 0, fpIntensity.rows(), 0, fpIntensity.cols(), m_focalPlane, x0, y0 );
 
 
  468template <
typename _realT, 
typename _fpmaskFloatT>
 
  471    applyApodizer( pupilPlane );
 
  473    m_fp.propagatePupilToFocal( m_focalPlane, pupilPlane );
 
  475    m_fp.propagateFocalToPupil( pupilPlane, m_focalPlane );
 
  477    applyLyotStop( pupilPlane );
 
 
  482template <
typename _realT, 
typename _fpmaskFloatT>
 
  485    propagateNC( pupilPlane );
 
  487    m_fp.propagatePupilToFocal( m_focalPlane, pupilPlane );
 
  489    int x0 = 0.5 * ( m_wfSz - 1 ) - 0.5 * ( fpIntensity.rows() - 1 );
 
  490    int y0 = 0.5 * ( m_wfSz - 1 ) - 0.5 * ( fpIntensity.cols() - 1 );
 
  492    extractIntensityImage( fpIntensity, 0, fpIntensity.rows(), 0, fpIntensity.cols(), m_focalPlane, x0, y0 );
 
 
  497template <
typename _realT, 
typename _fpmaskFloatT>
 
  499    imageT &geomPupil, 
realT fpmRadPix, 
realT relTol, 
realT absTol, 
int maxIter, 
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 )
 
  553            for( 
int j = 0; j < m_wfSz; ++j )
 
  554                pupilImage( i, j ) = abs( pupilPlane( i, j ) );
 
  557        for( 
int i = 0; i < m_wfSz; ++i )
 
  559            for( 
int j = 0; j < m_wfSz; ++j )
 
  561                if( i >= gpLLi && i < gpURi && j >= gpLLj && j < gpURj )
 
  563                    pupilImage( i, j ) *= geomPupil( i - gpLLi, j - gpLLj );
 
  564                    if( pupilImage( i, j ) > LambdaA )
 
  565                        LambdaA = pupilImage( i, j );
 
  569                    pupilImage( i, j ) = 0;
 
  574        for( 
int i = 0; i < m_wfSz; ++i )
 
  575            for( 
int j = 0; j < m_wfSz; ++j )
 
  576                pupilImage( i, j ) /= LambdaA;
 
  578        std::cout << n << 
" " << LambdaA << 
"\n";
 
  579        if( fabs( LambdaA - lastLambdaA ) < absTol )
 
  581            std::cout << 
"Converged on absTol.\n";
 
  585        if( fabs( ( LambdaA - lastLambdaA ) / lastLambdaA ) < relTol )
 
  587            std::cout << 
"Converged on relTol.\n";
 
  592        if( n == maxIter - 1 )
 
  594            std::cout << 
"maxIter reached.\n";
 
  598        lastLambdaA = LambdaA;
 
  603    std::cout << 
"LambdaA: = " << LambdaA << 
"\n";
 
  605    realT trans = 1.0 - 1.0 / LambdaA;
 
  607    int pupSize = geomPupil.rows();
 
  609    m_pupilApodizer.resize( pupSize, pupSize );
 
  617                  0.5 * ( ( pupilImage.rows() - 1 ) - ( pupSize - 1 ) ),
 
  618                  0.5 * ( ( pupilImage.rows() - 1 ) - ( pupSize - 1 ) ) );
 
  620    makeFocalMask( fpmRadPix, trans, pupSize );
 
  632    m_lyotStop = geomPupil;
 
  636    head.
append( 
"", fits::fitsCommentType(), 
"----------------------------------------" );
 
  637    head.
append( 
"", fits::fitsCommentType(), 
"lyotCoronagraph optimization Parameters:" );
 
  638    head.
append( 
"", fits::fitsCommentType(), 
"----------------------------------------" );
 
  639    head.
append<
int>( 
"WFSZ", m_wfSz, 
"Size of wavefront used for FFTs (pixels)" );
 
  640    head.
append<
realT>( 
"FPMRADPX", fpmRadPix, 
"input radius of focal plane mask (pixels)" );
 
  641    head.
append<
realT>( 
"ABSTOL", absTol, 
"input absolute tolerance" );
 
  642    head.
append<
realT>( 
"RELTOL", relTol, 
"input relative tolerance" );
 
  643    head.
append<
int>( 
"MAXITER", maxIter, 
"input maximum iterations" );
 
  644    head.
append<
int>( 
"NITER", n, 
"actual number of iterations" );
 
  645    head.
append<std::string>( 
"XREASON", reason, 
"reason for convergence" );
 
  646    head.
append<
realT>( 
"FPMTRANS", trans, 
"transmission of FPM" );
 
  650    std::string fname = 
"coron/" + cname + 
"_apod.fits";
 
  652    ff.
write( fname, m_pupilApodizer, head );
 
  654    fname = 
"coron/" + cname + 
"_fpm.fits";
 
  656    for( 
int r = 0; r < m_focalMask.rows(); ++r )
 
  658        for( 
int c = 0; c < m_focalMask.cols(); ++c )
 
  660            fpm( r, c ) = m_focalMask( r, c ).real();
 
  664    ff.write( fname, fpm, head );
 
  666    fname = 
"coron/" + cname + 
"_lyot.fits";
 
  667    ff.write( fname, m_lyotStop, head );
 
 
  670template <
typename _realT, 
typename _fpmaskFloatT>
 
  677                                                             const std::string &cname )
 
  681    pupilPlane.resize( m_wfSz, m_wfSz );
 
  682    focalPlane.resize( m_wfSz, m_wfSz );
 
  684    mx::wfp::imagingArray<realT, fftwAllocator<realT>, 0> mask( m_wfSz, m_wfSz );
 
  688    mx::wfp::imagingArray<realT, fftwAllocator<realT>, 0> pupilImage( m_wfSz, m_wfSz );
 
  689    pupilImage.setZero();
 
  691    int gpLLi = 0.5 * ( m_wfSz - 1 ) - 0.5 * ( geomPupil.rows() - 1 );
 
  692    int gpLLj = 0.5 * ( m_wfSz - 1 ) - 0.5 * ( geomPupil.cols() - 1 );
 
  694    int gpURi = gpLLi + geomPupil.rows();
 
  695    int gpURj = gpLLj + geomPupil.cols();
 
  697    for( 
int i = 0; i < geomPupil.rows(); ++i )
 
  699        for( 
int j = 0; j < geomPupil.cols(); ++j )
 
  701            pupilImage( gpLLi + i, gpLLj + j ) = geomPupil( i, j );
 
  705    realT lastLambdaA, LambdaA;
 
  710    for( n = 0; n < maxIter; ++n )
 
  714        m_fp.propagatePupilToFocal( focalPlane, pupilPlane );
 
  716        for( 
int i = 0; i < m_wfSz; ++i )
 
  718            for( 
int j = 0; j < m_wfSz; ++j )
 
  720                focalPlane( i, j ) *= mask( i, j ) * exp( std::complex<realT>( 0, fpmPhase( i, j ) ) );
 
  725        m_fp.propagateFocalToPupil( pupilPlane, focalPlane );
 
  727        for( 
int i = 0; i < m_wfSz; ++i )
 
  728            for( 
int j = 0; j < m_wfSz; ++j )
 
  729                pupilImage( i, j ) = abs( pupilPlane( i, j ) );
 
  732        for( 
int i = 0; i < m_wfSz; ++i )
 
  734            for( 
int j = 0; j < m_wfSz; ++j )
 
  736                if( i >= gpLLi && i < gpURi && j >= gpLLj && j < gpURj )
 
  738                    pupilImage( i, j ) *= geomPupil( i - gpLLi, j - gpLLj );
 
  739                    if( pupilImage( i, j ) > LambdaA )
 
  740                        LambdaA = pupilImage( i, j );
 
  744                    pupilImage( i, j ) = 0;
 
  749        for( 
int i = 0; i < m_wfSz; ++i )
 
  750            for( 
int j = 0; j < m_wfSz; ++j )
 
  751                pupilImage( i, j ) /= LambdaA;
 
  753        std::cout << n << 
" " << LambdaA << 
"\n";
 
  754        if( fabs( LambdaA - lastLambdaA ) < absTol )
 
  756            std::cout << 
"Converged on absTol.\n";
 
  760        if( fabs( ( LambdaA - lastLambdaA ) / lastLambdaA ) < relTol )
 
  762            std::cout << 
"Converged on relTol.\n";
 
  767        if( n == maxIter - 1 )
 
  769            std::cout << 
"maxIter reached.\n";
 
  773        lastLambdaA = LambdaA;
 
  778    std::cout << 
"LambdaA: = " << LambdaA << 
"\n";
 
  780    realT trans = 1.0 - 1.0 / LambdaA;
 
  782    int pupSize = geomPupil.rows();
 
  784    m_pupilApodizer.resize( pupSize, pupSize );
 
  792                  0.5 * ( ( pupilImage.rows() - 1 ) - ( pupSize - 1 ) ),
 
  793                  0.5 * ( ( pupilImage.rows() - 1 ) - ( pupSize - 1 ) ) );
 
  795    makeFocalMask( fpmRadPix, trans, pupSize );
 
  798    m_lyotStop = geomPupil;
 
  802    head.
append( 
"", fits::fitsCommentType(), 
"----------------------------------------" );
 
  803    head.
append( 
"", fits::fitsCommentType(), 
"lyotCoronagraph optimization Parameters:" );
 
  804    head.
append( 
"", fits::fitsCommentType(), 
"----------------------------------------" );
 
  805    head.
append<
int>( 
"WFSZ", m_wfSz, 
"Size of wavefront used for FFTs (pixels)" );
 
  806    head.
append<
realT>( 
"FPMRADPX", fpmRadPix, 
"input radius of focal plane mask (pixels)" );
 
  807    head.
append<
realT>( 
"ABSTOL", absTol, 
"input absolute tolerance" );
 
  808    head.
append<
realT>( 
"RELTOL", relTol, 
"input relative tolerance" );
 
  809    head.
append<
int>( 
"MAXITER", maxIter, 
"input maximum iterations" );
 
  810    head.
append<
int>( 
"NITER", n, 
"actual number of iterations" );
 
  811    head.
append<std::string>( 
"XREASON", reason, 
"reason for convergence" );
 
  812    head.
append<
realT>( 
"FPMTRANS", trans, 
"transmission of FPM" );
 
  816    std::string fname = 
"coron/" + cname + 
"_apod.fits";
 
  818    ff.
write( fname, m_pupilApodizer, head );
 
  820    fname = 
"coron/" + cname + 
"_fpm.fits";
 
  822    for( 
int r = 0; r < m_focalMask.rows(); ++r )
 
  824        for( 
int c = 0; c < m_focalMask.cols(); ++c )
 
  826            fpm( r, c ) = m_focalMask( r, c ).real();
 
  830    ff.write( fname, fpm, head );
 
  832    fname = 
"coron/" + cname + 
"_lyot.fits";
 
  833    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.
 
Class to perform Fraunhofer propagation between pupil and focal planes.
 
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.
 
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.