mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
Loading...
Searching...
No Matches
lyotCoronagraph.hpp
Go to the documentation of this file.
1/** \file lyotCoronagraph.hpp
2 * \brief Declares and defines a class to describe and optimize a Lyot Coronagraph.
3 * \ingroup imaging_files
4 * \author Jared R. Males (jaredmales@gmail.com)
5 *
6 */
7
8//***********************************************************************//
9// Copyright 2015, 2016, 2017, 2018 Jared R. Males (jaredmales@gmail.com)
10//
11// This file is part of mxlib.
12//
13// mxlib is free software: you can redistribute it and/or modify
14// it under the terms of the GNU General Public License as published by
15// the Free Software Foundation, either version 3 of the License, or
16// (at your option) any later version.
17//
18// mxlib is distributed in the hope that it will be useful,
19// but WITHOUT ANY WARRANTY; without even the implied warranty of
20// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21// GNU General Public License for more details.
22//
23// You should have received a copy of the GNU General Public License
24// along with mxlib. If not, see <http://www.gnu.org/licenses/>.
25//***********************************************************************//
26
27#ifndef __lyotCoronagraph_hpp__
28#define __lyotCoronagraph_hpp__
29
30#include <iostream>
31
32#include "imagingArray.hpp"
33#include "imagingUtils.hpp"
35
38
40
43
44namespace mx
45{
46
47namespace wfp
48{
49
50/// The Lyot Coronagraph
51/** A generalized Lyot coronagraph, which can include a pupil apodization, a focal plane mask with complex transmission,
52 * and a Lyot stop. Light is propagated through the coronagraph plane-by-plane, and the complex wavefront can be
53 * accessed at any plane. Also provides functions for optimizing the pupil apodizer and focal plane mask.
54 *
55 * \ingroup coronagraphs
56 */
57template <typename _realT, typename _fpmaskFloatT>
59{
60 public:
61 /// The real floating point type
62 typedef _realT realT;
63
64 /// The real floating point type for mask calculations.
65 typedef _fpmaskFloatT fpmaskFloatT;
66
67 /// The complex floating point type
68 typedef std::complex<realT> complexT;
69
70 /// The wavefront complex field type
71 typedef mx::wfp::imagingArray<std::complex<realT>, fftwAllocator<std::complex<realT>>, 0> complexFieldT;
72
73 /// The focal plane mask type
74 typedef Eigen::Array<std::complex<fpmaskFloatT>, Eigen::Dynamic, Eigen::Dynamic> fpMaskT;
75
76 /// The image type
77 typedef Eigen::Array<realT, Eigen::Dynamic, Eigen::Dynamic> imageT;
78
79 public:
80 /// The directory where coronagraph files are stored
81 std::string m_fileDir{ "coron" };
82
83 /// The linear size of the wavefront in pixels
84 int m_wfSz{ 0 };
85
86 /// Image containing the pupil apodization.
88
89 int m_maskSource; ///< 0= read from file, 1 = constructed by makeFocalMask, 2 = trans optimized.
90 std::string m_maskFile; ///< Name of file from which mask was loaded.
91
92 realT m_maskRad; ///< Radius of mask if it was constructed.
93 realT m_maskTrans; ///< Transmission of mask if it was constructed.
94
95 /// The focal plane mask.
97
98 /// Image containing the lyot stop.
100
101 complexFieldT m_focalPlane;
102
103 bool m_savePreMaskFocalPlane{ false };
104 complexFieldT m_preMaskFocalPlane;
105
106 bool m_savePreLyotPupilPlane{ false };
107 complexFieldT m_preLyotPupilPlane;
108
109 /// Fraunhofer propagator
111
112 public:
113 /// Default c'tor
115
116 /// Get the wavefront size in pixels
117 /**
118 * \returns the wavefront size in pixels
119 */
120 int wfSz();
121
122 /// Set the wavefront size in pixels.
123 /**
124 */
125 void wfSz( int sz /**< [in] is the new size */ );
126
127 /// Make the focal plane mask
128 void makeFocalMask( realT rad, fpmaskFloatT trans = 0.0, int sz = 0.0 );
129
130 /// Load the apodizer from a FITS file
131 /**
132 * \returns 0 on success.
133 * \returns -1 on error.
134 */
135 int loadApodizer( const std::string &apodName /**< [in] is the name of the FITS file containing the apodizer. */ );
136
137 /// Load the focal plane mask from a FITS file
138 /**
139 * \returns 0 on success.
140 * \returns -1 on error.
141 */
142 int loadFocalMask(
143 const std::string &fpmName /**< [in] is the name of the FITS file containing the focal plane mask. */ );
144
145 /// Load the Lyot stop from a FITS file
146 /**
147 * \returns 0 on success.
148 * \returns -1 on error.
149 */
150 int loadLyotStop( const std::string &lyotName /**< [in] is the name of the FITS file containing the lyot stop. */ );
151
152 /// Load the components of the coronagraph from FITS files
153 /**
154 * \returns 0 on success.
155 * \returns -1 on error.
156 */
157 int
158 loadCoronagraph( const std::string &apodName, ///< [in] is the name of the FITS file containing the apodizer.
159 const std::string &fpmName, ///< [in] is the name of the FITS file containing the focal plane mask.
160 const std::string &lyotName ///< [in] is the name of the FITS file containing the lyot stop.
161 );
162
163 /// Load the components of the coronagraph based in its base name
164 /** Looks in _filDir for the files.
165 *
166 * \returns 0 on success.
167 * \returns -1 on error.
168 */
169 int
170 loadCoronagraph( const std::string
171 &cName /**< [in] is the base name of the coronagraph without directory or file extension. */ );
172
173 void applyApodizer( complexFieldT &pupilPlane );
174 void applyFocalMask( complexFieldT &focalPlane );
175 void applyLyotStop( complexFieldT &lyotPlane );
176
177 /// Propagate the given pupil-plane wavefront through the coronagraph.
178 int propagate(
180 &pupilPlane /**< [in.out] The wavefront at the input pupil plane. It is modified by the coronagraph. */ );
181
182 int
183 propagate( imageT &fpIntensity, ///< [out] The intensity image in the focal plane. This should be pre-allocated.
185 &pupilPlane ///< [in.out] The wavefront at the input pupil plane. It is modified by the coronagraph.
186 );
187
188 /// Propagate the given pupil-plane wavefront without the coronagraph.
189 /** For a Lyot coronagraph, this applies the pupil apodization and Lyot stop, but not the FPM, to the given
190 * pupil-plane wavefront such that the result will produce the non-coronagraphic (off-axis) PSF.
191 */
192 int propagateNC(
194 &pupilPlane /**< [in.out] The wavefront at the input pupil plane. It is modified by the coronagraph. */ );
195
196 int propagateNC(
197 imageT &fpIntensity, ///< [out] The intensity image in the focal plane. This should be pre-allocated.
199 &pupilPlane ///< [in.out] The wavefront at the input pupil plane. It is modified by the coronagraph.
200 );
201
202 /// Optimize the pupil amplitude apodization and focal-plane mask complex transmission.
203 /** Uses the algorithm in Guyon (2014) \cite guyon_2014 for optimizing an Apodized-Pupil Lyot Complex Mask
204 * Coronagraph (APLCMC).
205 *
206 */
207 void
208 optimizeAPLCMC( imageT &geomPupil, ///< The geometric pupil mask, binary 1/0 transmission.
209 realT fpmRadPix, ///< The radius in pixels of the FPM.
210 realT relTol, ///< Relative tolerance for convergence.
211 realT absTol, ///< Absolute tolerance for convergence.
212 int maxIter, ///< Maximum number of iterations to allow.
213 const std::string &cname ///< Name of coronagraph, used as base-name for output files in m_fileDir.
214 );
215
216 void
217 optimizeAPLCMC( imageT &geomPupil, ///< The geometric pupil mask, binary 1/0 transmission.
218 realT fpmRadPix, ///< The radius in pixels of the FPM.
219 imageT &fpmPhase,
220 realT relTol, ///< Relative tolerance for convergence.
221 realT absTol, ///< Absolute tolerance for convergence.
222 int maxIter, ///< Maximum number of iterations to allow.
223 const std::string &cname ///< Name of coronagraph, used as base-name for output files in m_fileDir.
224 );
225};
226
227template <typename _realT, typename _fpmaskFloatT>
231
232template <typename _realT, typename _fpmaskFloatT>
237
238template <typename _realT, typename _fpmaskFloatT>
240{
241 m_wfSz = sz;
242
243 m_fp.setWavefrontSizePixels( sz );
244 m_focalPlane.resize( sz, sz );
245}
246
247template <typename _realT, typename _fpmaskFloatT>
248void lyotCoronagraph<_realT, _fpmaskFloatT>::makeFocalMask( _realT rad, _fpmaskFloatT trans, int sz )
249{
250 if( sz == 0 )
251 {
252 sz = 2 * rad + 1;
253 if( sz % 2 == 1 )
254 ++sz;
255 }
256
257 // Make a real circular mask
259 mx::wfp::circularPupil( fpm, 0., rad );
260
261 // Convert to complex amplitude
262 m_focalMask.resize( sz, sz );
263 for( int i = 0; i < sz; ++i )
264 {
265 for( int j = 0; j < sz; ++j )
266 {
267 if( fpm( i, j ) == 1 )
268 m_focalMask( i, j ) = std::complex<fpmaskFloatT>( trans, 0 );
269 else
270 m_focalMask( i, j ) = std::complex<fpmaskFloatT>( 1, 0 );
271 }
272 }
273
274 m_maskSource = 1;
275 m_maskFile = "";
276 m_maskRad = rad;
277 m_maskTrans = 0.0;
278}
279
280template <typename _realT, typename _fpmaskFloatT>
282{
284
285 if( !!ff.read( m_pupilApodizer, apodName ) )
286 return -1;
287
288 return 0;
289}
290
291template <typename _realT, typename _fpmaskFloatT>
293{
296
297 if( !!ff.read( fpm, fpmName ) )
298 return -1;
299
300 if( fpm.planes() == 1 )
301 {
302 m_focalMask = fpm.image( 0 );
303 }
304 else if( fpm.planes() == 2 )
305 {
306 m_focalMask.resize( fpm.rows(), fpm.cols() );
307
308 for( int r = 0; r < fpm.rows(); ++r )
309 {
310 for( int c = 0; c < fpm.cols(); ++c )
311 {
312 m_focalMask( r, c ) =
313 fpm.image( 0 )( r, c ) * exp( std::complex<fpmaskFloatT>( 0, fpm.image( 1 )( r, c ) ) );
314 }
315 }
316 }
317 else
318 {
319 std::cerr << "too many planes in focal mask file\n";
320 return -1;
321 }
322
323 m_maskSource = 0;
324 m_maskFile = fpmName;
325 m_maskRad = 0.0;
326 m_maskTrans = 0.0;
327
328 return 0;
329}
330
331template <typename _realT, typename _fpmaskFloatT>
333{
335
336 if( !!ff.read( m_lyotStop, lyotName ) )
337 return -1;
338
339 return 0;
340}
341
342template <typename _realT, typename _fpmaskFloatT>
344 const std::string &fpmName,
345 const std::string &lyotName )
346{
347 if( loadApodizer( apodName ) < 0 )
348 return -1;
349 if( loadFocalMask( fpmName ) < 0 )
350 return -1;
351 if( loadLyotStop( lyotName ) < 0 )
352 return -1;
353
354 return 0;
355}
356
357template <typename _realT, typename _fpmaskFloatT>
359{
360 if( m_fileDir == "" )
361 {
362 mxError( "lyotCoronagraph", MXE_PARAMNOTSET, "file directory (fileDir) not set." );
363 return -1;
364 }
365
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";
369
370 return loadCoronagraph( apodName, fpmName, lyotName );
371}
372
373template <typename _realT, typename _fpmaskFloatT>
374void lyotCoronagraph<_realT, _fpmaskFloatT>::applyApodizer( complexFieldT &pupilPlane )
375{
376 int sz = m_pupilApodizer.rows();
377
378 realT w = 0.5 * ( sz - 1.0 );
379
380 realT xc = 0.5 * ( pupilPlane.rows() - 1 );
381 realT yc = 0.5 * ( pupilPlane.cols() - 1 );
382
383 for( int i = 0; i < pupilPlane.rows(); ++i )
384 {
385 for( int j = 0; j < pupilPlane.cols(); ++j )
386 {
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 ) ) );
389 else
390 pupilPlane( i, j ) *= 0;
391 }
392 }
393}
394
395template <typename _realT, typename _fpmaskFloatT>
396void lyotCoronagraph<_realT, _fpmaskFloatT>::applyFocalMask( complexFieldT &focalPlane )
397{
398 int sz = m_focalMask.rows();
399
400 realT w = 0.5 * ( sz - 1.0 );
401
402 realT xc = 0.5 * ( focalPlane.rows() - 1 );
403 realT yc = 0.5 * ( focalPlane.cols() - 1 );
404
405 for( int i = 0; i < sz; ++i )
406 {
407 for( int j = 0; j < sz; ++j )
408 {
409 focalPlane( xc - w + i, yc - w + j ) *= m_focalMask( i, j );
410 }
411 }
412}
413
414template <typename _realT, typename _fpmaskFloatT>
415void lyotCoronagraph<_realT, _fpmaskFloatT>::applyLyotStop( complexFieldT &lyotPlane )
416{
417 int sz = m_lyotStop.rows();
418
419 realT w = 0.5 * ( sz - 1.0 );
420
421 realT xc = 0.5 * ( lyotPlane.rows() - 1 );
422 realT yc = 0.5 * ( lyotPlane.cols() - 1 );
423
424 for( int i = 0; i < lyotPlane.rows(); ++i )
425 {
426 for( int j = 0; j < lyotPlane.cols(); ++j )
427 {
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 ) ) );
430 else
431 lyotPlane( i, j ) = 0;
432 }
433 }
434}
435
436template <typename _realT, typename _fpmaskFloatT>
438{
439 applyApodizer( pupilPlane );
440
441 m_fp.propagatePupilToFocal( m_focalPlane, pupilPlane );
442
443 if( m_savePreMaskFocalPlane )
444 {
445 m_preMaskFocalPlane = m_focalPlane;
446 }
447
448 applyFocalMask( m_focalPlane );
449
450 m_fp.propagateFocalToPupil( pupilPlane, m_focalPlane );
451
452 if( m_savePreLyotPupilPlane )
453 {
454 m_preLyotPupilPlane = pupilPlane;
455 }
456
457 applyLyotStop( pupilPlane );
458
459 return 0;
460}
461
462template <typename _realT, typename _fpmaskFloatT>
464{
465 propagate( pupilPlane );
466
467 m_fp.propagatePupilToFocal( m_focalPlane, pupilPlane );
468
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 );
471
472 extractIntensityImage( fpIntensity, 0, fpIntensity.rows(), 0, fpIntensity.cols(), m_focalPlane, x0, y0 );
473
474 return 0;
475}
476template <typename _realT, typename _fpmaskFloatT>
478{
479 applyApodizer( pupilPlane );
480
481 m_fp.propagatePupilToFocal( m_focalPlane, pupilPlane );
482
483 m_fp.propagateFocalToPupil( pupilPlane, m_focalPlane );
484
485 applyLyotStop( pupilPlane );
486
487 return 0;
488}
489
490template <typename _realT, typename _fpmaskFloatT>
492{
493 propagateNC( pupilPlane );
494
495 m_fp.propagatePupilToFocal( m_focalPlane, pupilPlane );
496
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 );
499
500 extractIntensityImage( fpIntensity, 0, fpIntensity.rows(), 0, fpIntensity.cols(), m_focalPlane, x0, y0 );
501
502 return 0;
503}
504
505template <typename _realT, typename _fpmaskFloatT>
507 imageT &geomPupil, realT fpmRadPix, realT relTol, realT absTol, int maxIter, const std::string &cname )
508{
509 complexFieldT focalPlane, pupilPlane;
510
511 pupilPlane.resize( m_wfSz, m_wfSz );
512 focalPlane.resize( m_wfSz, m_wfSz );
513
514 mx::wfp::imagingArray<realT, fftwAllocator<realT>, 0> mask( m_wfSz, m_wfSz );
515 mx::wfp::circularPupil( mask, 0., fpmRadPix );
516 /*for(int c=0; c< mask.cols()*0.5; ++c)
517 {
518 for(int r=0; r < mask.rows(); ++r) mask(r,c) = 0;
519 }*/
520
521 // Initialize pupilImage
522 mx::wfp::imagingArray<realT, fftwAllocator<realT>, 0> pupilImage( m_wfSz, m_wfSz );
523 pupilImage.setZero();
524
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 );
527
528 int gpURi = gpLLi + geomPupil.rows();
529 int gpURj = gpLLj + geomPupil.cols();
530
531 for( int i = 0; i < geomPupil.rows(); ++i )
532 {
533 for( int j = 0; j < geomPupil.cols(); ++j )
534 {
535 pupilImage( gpLLi + i, gpLLj + j ) = geomPupil( i, j );
536 }
537 }
538
539 realT lastLambdaA, LambdaA;
540
541 lastLambdaA = 1;
542 int n;
543 std::string reason;
544 for( n = 0; n < maxIter; ++n )
545 {
546 mx::wfp::makeComplexPupil( pupilPlane, pupilImage, m_wfSz );
547
548 m_fp.propagatePupilToFocal( focalPlane, pupilPlane );
549
550 for( int i = 0; i < m_wfSz; ++i )
551 {
552 for( int j = 0; j < m_wfSz; ++j )
553 {
554 focalPlane( i, j ) *= mask( i, j );
555 }
556 }
557
558 m_fp.propagateFocalToPupil( pupilPlane, focalPlane );
559
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 ) );
563
564 LambdaA = 0;
565 for( int i = 0; i < m_wfSz; ++i )
566 {
567 for( int j = 0; j < m_wfSz; ++j )
568 {
569 if( i >= gpLLi && i < gpURi && j >= gpLLj && j < gpURj )
570 {
571 pupilImage( i, j ) *= geomPupil( i - gpLLi, j - gpLLj );
572 if( pupilImage( i, j ) > LambdaA )
573 LambdaA = pupilImage( i, j );
574 }
575 else
576 {
577 pupilImage( i, j ) = 0;
578 }
579 }
580 }
581 // LambdaA = 1.0/LambdaA;
582 for( int i = 0; i < m_wfSz; ++i )
583 for( int j = 0; j < m_wfSz; ++j )
584 pupilImage( i, j ) /= LambdaA;
585
586 std::cout << n << " " << LambdaA << "\n";
587 if( fabs( LambdaA - lastLambdaA ) < absTol )
588 {
589 std::cout << "Converged on absTol.\n";
590 reason = "absTol";
591 break;
592 }
593 if( fabs( ( LambdaA - lastLambdaA ) / lastLambdaA ) < relTol )
594 {
595 std::cout << "Converged on relTol.\n";
596 reason = "relTol";
597 break;
598 }
599
600 if( n == maxIter - 1 )
601 {
602 std::cout << "maxIter reached.\n";
603 reason = "maxIter";
604 }
605
606 lastLambdaA = LambdaA;
607 }
608 if( LambdaA > 1 )
609 LambdaA = 1;
610
611 std::cout << "LambdaA: = " << LambdaA << "\n";
612
613 realT trans = 1.0 - 1.0 / LambdaA;
614
615 int pupSize = geomPupil.rows();
616
617 m_pupilApodizer.resize( pupSize, pupSize );
618
620 0,
621 pupSize,
622 0,
623 pupSize,
624 pupilImage,
625 0.5 * ( ( pupilImage.rows() - 1 ) - ( pupSize - 1 ) ),
626 0.5 * ( ( pupilImage.rows() - 1 ) - ( pupSize - 1 ) ) );
627
628 makeFocalMask( fpmRadPix, trans, pupSize );
629
630 /*for(int c=0; c< m_focalMask.cols()*0.5; ++c)
631 {
632 for(int r=0; r < m_focalMask.rows(); ++r)
633 {
634 if(m_focalMask(r,c).real()==1) m_focalMask(r,c) = 0;
635 }
636 }*/
637
638 m_maskSource = 2;
639
640 m_lyotStop = geomPupil;
641
642 fits::fitsHeader head;
643
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" );
655
657
658 std::string fname = "coron/" + cname + "_apod.fits";
659
660 ff.write( fname, m_pupilApodizer, head );
661
662 fname = "coron/" + cname + "_fpm.fits";
664 for( int r = 0; r < m_focalMask.rows(); ++r )
665 {
666 for( int c = 0; c < m_focalMask.cols(); ++c )
667 {
668 fpm( r, c ) = m_focalMask( r, c ).real();
669 }
670 }
671
672 ff.write( fname, fpm, head );
673
674 fname = "coron/" + cname + "_lyot.fits";
675 ff.write( fname, m_lyotStop, head );
676}
677
678template <typename _realT, typename _fpmaskFloatT>
680 realT fpmRadPix,
681 imageT &fpmPhase,
682 realT relTol,
683 realT absTol,
684 int maxIter,
685 const std::string &cname )
686{
687 complexFieldT focalPlane, pupilPlane;
688
689 pupilPlane.resize( m_wfSz, m_wfSz );
690 focalPlane.resize( m_wfSz, m_wfSz );
691
692 mx::wfp::imagingArray<realT, fftwAllocator<realT>, 0> mask( m_wfSz, m_wfSz );
693 mx::wfp::circularPupil( mask, 0., fpmRadPix );
694
695 // Initialize pupilImage
696 mx::wfp::imagingArray<realT, fftwAllocator<realT>, 0> pupilImage( m_wfSz, m_wfSz );
697 pupilImage.setZero();
698
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 );
701
702 int gpURi = gpLLi + geomPupil.rows();
703 int gpURj = gpLLj + geomPupil.cols();
704
705 for( int i = 0; i < geomPupil.rows(); ++i )
706 {
707 for( int j = 0; j < geomPupil.cols(); ++j )
708 {
709 pupilImage( gpLLi + i, gpLLj + j ) = geomPupil( i, j );
710 }
711 }
712
713 realT lastLambdaA, LambdaA;
714
715 lastLambdaA = 1;
716 int n;
717 std::string reason;
718 for( n = 0; n < maxIter; ++n )
719 {
720 mx::wfp::makeComplexPupil( pupilPlane, pupilImage, m_wfSz );
721
722 m_fp.propagatePupilToFocal( focalPlane, pupilPlane );
723
724 for( int i = 0; i < m_wfSz; ++i )
725 {
726 for( int j = 0; j < m_wfSz; ++j )
727 {
728 focalPlane( i, j ) *= mask( i, j ) * exp( std::complex<realT>( 0, fpmPhase( i, j ) ) );
729 ;
730 }
731 }
732
733 m_fp.propagateFocalToPupil( pupilPlane, focalPlane );
734
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 ) );
738
739 LambdaA = 0;
740 for( int i = 0; i < m_wfSz; ++i )
741 {
742 for( int j = 0; j < m_wfSz; ++j )
743 {
744 if( i >= gpLLi && i < gpURi && j >= gpLLj && j < gpURj )
745 {
746 pupilImage( i, j ) *= geomPupil( i - gpLLi, j - gpLLj );
747 if( pupilImage( i, j ) > LambdaA )
748 LambdaA = pupilImage( i, j );
749 }
750 else
751 {
752 pupilImage( i, j ) = 0;
753 }
754 }
755 }
756 // LambdaA = 1.0/LambdaA;
757 for( int i = 0; i < m_wfSz; ++i )
758 for( int j = 0; j < m_wfSz; ++j )
759 pupilImage( i, j ) /= LambdaA;
760
761 std::cout << n << " " << LambdaA << "\n";
762 if( fabs( LambdaA - lastLambdaA ) < absTol )
763 {
764 std::cout << "Converged on absTol.\n";
765 reason = "absTol";
766 break;
767 }
768 if( fabs( ( LambdaA - lastLambdaA ) / lastLambdaA ) < relTol )
769 {
770 std::cout << "Converged on relTol.\n";
771 reason = "relTol";
772 break;
773 }
774
775 if( n == maxIter - 1 )
776 {
777 std::cout << "maxIter reached.\n";
778 reason = "maxIter";
779 }
780
781 lastLambdaA = LambdaA;
782 }
783 if( LambdaA > 1 )
784 LambdaA = 1;
785
786 std::cout << "LambdaA: = " << LambdaA << "\n";
787
788 realT trans = 1.0 - 1.0 / LambdaA;
789
790 int pupSize = geomPupil.rows();
791
792 m_pupilApodizer.resize( pupSize, pupSize );
793
795 0,
796 pupSize,
797 0,
798 pupSize,
799 pupilImage,
800 0.5 * ( ( pupilImage.rows() - 1 ) - ( pupSize - 1 ) ),
801 0.5 * ( ( pupilImage.rows() - 1 ) - ( pupSize - 1 ) ) );
802
803 makeFocalMask( fpmRadPix, trans, pupSize );
804 m_maskSource = 2;
805
806 m_lyotStop = geomPupil;
807
808 fits::fitsHeader head;
809
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" );
821
823
824 std::string fname = "coron/" + cname + "_apod.fits";
825
826 ff.write( fname, m_pupilApodizer, head );
827
828 fname = "coron/" + cname + "_fpm.fits";
830 for( int r = 0; r < m_focalMask.rows(); ++r )
831 {
832 for( int c = 0; c < m_focalMask.cols(); ++c )
833 {
834 fpm( r, c ) = m_focalMask( r, c ).real();
835 }
836 }
837
838 ff.write( fname, fpm, head );
839
840 fname = "coron/" + cname + "_lyot.fits";
841 ff.write( fname, m_lyotStop, head );
842}
843
844} // namespace wfp
845} // namespace mx
846
847#endif //__lyotCoronagraph_hpp__
Class to manage interactions with a FITS file.
Definition fitsFile.hpp:84
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.
Class to manage a FITS file metadata header and provide fast access to the cards by keyword.
error_t append(const fitsHeaderCard< verboseT > &card)
Append a fitsHeaderCard to the end of the header.
An image cube with an Eigen-like API.
Definition eigenCube.hpp:33
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.
The mxlib c++ namespace.
Definition mxlib.hpp:37
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.
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.