Coronagraph
Overview
The coronagraph module simulates electric field propagation through a coronagraph located downstream the AO loop. The input is the target residual phase, and the main output is the coronagraph image. Two types of coronagraphs are implemented : a perfect coronagraph and a more realistic coronagraph called four-plane coronagraph hereafter.
Perfect coronagraph
The perfect coronagraph substracts the diffractive effect of the telescope. Mathematically speaking, the following operations are performed:
- Electric field is computed from the incoming phase screen
- The average of the electric field over the pupil is substracted to the electric field
- Optical Fourier transform and square modulus yield the image in focal plane
References : Galicher, Raphaël : PhD thesis, section I.2.2.4 Sauvage, Jean-François : PhD thesis, section 2.4.3.1
Four-plane coronagraph
The four-plane coronagraph includes the different pupil and focal planes of a stellar coronagraph, in this order following the light in the instrument:
- an amplitude apodizer located in a pupil plane
- a focal plane mask located in a focal plane
- a Lyot stop located in a pupil plane
- and the image plane located in a focal plane.
An optical Fourier transform is performed to propagate the electric field from one plane to the next one. In the image plane, the square modulus of the electric field is computed.
For the four-plane coronagraph, you have the choice between the APLCs of SPHERE (Beuzit et al., 2019) and a user-defined coronagraph.
Images and PSF
The coronagraph module delivers the coronagraph image and the image with no coronagraph that we call point spread function (PSF) hereafter. The PSF is computed with the same residual phase than the coronagraph image. For the four-plane coronagraph, the PSF is computed without focal plane mask but with apodizer and Lyot stop. For the perfect coronagraph, the PSF is computed by removing the step number two in the description of “Perfect coronagraph”.
The image is centered between four pixels while the PSF is centered on one pixel. Both the coronagraph image and the PSF are without any noise and normalized to the maximum intensity of the diffraction pattern. The diffraction pattern is computed the same way as the PSF but with a flat incoming wavefront.
Polychromatism
The coronagraph module can handle polychromatic image formation. The simulated wavelengths are evenly distributed in $$ \left[ \lambda_0 - \Delta \lambda / 2, \lambda_0 + \Delta \lambda / 2 \right]$$ where λ0 is the coronagraph wavelength and Δλ the spectral bandwidth.
The incoming AO residual from Compass is a unique optical path difference screen, in micron, assumed to be achromatic. For each simulated wavelength, an electric field screen is computed from this optical path difference. Those screens are propagated through the coronagraph. The resulting image intensity is the sum of intensities for each simulated wavelength.
How to use it in Compass
Interface with the simulation
The coronagraph is a supervisor component, as well as a wfs, a dm or a rtc. During a simulation, the useful commands are available in the instance supervisor.corono
. They are briefly described below. Please take a look at the docstrings for more technical information.
Every methods take as first parameter coro_index
, namely the index of the coronagraph. Indeed, several coronagraphs may be used in the same simulation. The indexing is defined by the parameter file (see next section).
-
supervisor.corono.get_image(coro_index, expo_type='le')
Return the image. Ifexpo_type='le'
(default), return the long exposure image. Ifexpo_type='se'
, return the short exposure one. -
supervisor.corono.get_psf(coro_index, expo_type='le')
Return the coronagraph PSF. Ifexpo_type='le'
(default), return the long exposure PSF. Ifexpo_type='se'
, return the short exposure one. -
supervisor.corono.get_contrast(coro_index, expo_type='le', d_min=None, d_max=None, width=None, normalized_by_psf=True)
Return azimuthal average, standard deviation, minimum and maximum of image intensity, at several angular distances from the optical axis. By default, image intensity is normalized by the maximum of the PSF. -
supervisor.corono.reset(coro_index=None)
Reset the integration of long exposure image and PSF. -
supervisor.corono.compute_image(coro_index, comp_psf=True, accumulate=True)
Compute the short exposure image, and accumulate it in the long exposure image. Might be useful if you need to overwrite the supervisor.next() method. -
supervisor.corono.compute_psf(coro_index, accumulate)
Compute the short exposure PSF, and accumulate it in the long exposure PSF. Again, might be useful if you need to overwrite the supervisor.next() method.
Parameter file
The coronagraphs are defined in the Compass parameter file through the configuration class config.Param_corono
. To add one or more coronagraphs in the simulation, you need to set a list called p_coronos
and filled with Param_corono()
instances. Then you may choose the parameters y using the associated setters. For example :
p_corono0 = conf.Param_corono()
p_corono1 = conf.Param_corono()
p_coronos = [p_corono0, p_corono1]
p_corono0.set_type('SPHERE_APLC') # type of coronograph
p_corono0.set_wavelength_0(1.6) # [μm] wavelength
p_corono1.set_type('perfect')
p_corono1.set_wavelength_0(1.6)
p_corono1.set_dim_image(200) # [pixel] size of the science image
p_corono1.set_image_sampling(3.5) # [pixel] size of lambda/D in pixel
For each coronagraph, one of the required parameters is its type. You may choose between the SPHERE APLC, a perfect coronagraph or a user-defined coronagraph. Some parameters are common to every types, and some are specific. Those parameters are described in the following three sections.
SPHERE APLC
Type of coronagraph to set : p_corono.set_type('SPHERE_APLC')
Required parameters
p_corono.set_wavelength_0(float)
Coronagraph wavelength in micron. This parameter is called λ hereafter.
Optional parameters
-
p_corono.set_dim_image(int)
Size of the science image in pixel. -
p_corono.set_image_sampling(float)
Number of pixel per λ/D in the image plane. For instance, 2 is Shannon sampling. Default : auto computed value that matches SPHERE IRDIS pixel scale. -
p_corono.set_delta_wav(float)
Spectral bandwidth in micron. Default = 0. -
p_corono.set_nb_wav(int)
Number of simulated wavelengths in the spectral bandwidth. Default = 1. You need to set bothdelta_wav
andnb_wav
if you want polychromatic light. -
p_corono.set_focal_plane_name(str)
Name of the focal plane mask to use. Only the ALC masks are available for now. They are calledSPHERE_APLC_fpm_ALC1
, of diameter 145 mas,SPHERE_APLC_fpm_ALC2
, of diameter 185 mas, andSPHERE_APLC_fpm_ALC3
, of diameter 240 mas. Default isSPHERE_APLC_fpm_ALC2
. -
p_corono.set_fpm_sampling(float)
Number of pixels per λ/D in the mask plane. Default is 20 (such high value has been chosen because a Babinet propagation method is used).
Perfect coronagraph
Type of coronagraph to set : p_corono.set_type('perfect')
Required parameters : wavelength_0, dim_image, image_sampling
Optional parameters : delta_wav, nb_wav
User-defined coronagraph
Type of coronagraph to set : p_corono.set_type('custom')
Required parameters :
-
wavelength_0, dim_image, image_sampling
-
p_corono.set_apodizer_name(str)
Apodizer keyword, or path to a fits file. Only the apodizer of SPHERE called APO1 is coded in Compass. It is accessible with the keywordSPHERE_APLC_apodizer_APO1
. Otherwise, you may set your own apodizer with a path to a fits file of size(pupdiam, pupdiam)
. The integerpupdiam
is the Compass pupil diameter in pixel. -
p_corono.set_focal_plane_mask_name(str)
Focal plane mask keyword, or path to a fits file. You may choose between a Lyot round mask calledclassical_Lyot
or one of the keywords for the SPHERE ALC masks (which are round masks with hardcoded diameter). To use your own focal plane mask, set a path to a fits file of size(dim_fpm, dim_fpm)
. Your focal plane mask sizedim_fpm
in pixel is automatically detected by Compass during initialization. For polychromatic masks, you may use a 3D array of size(dim_fpm, dim_fpm, nb_wav)
, the third dimension corresponding to the simulated wavelengths. -
p_corono.set_fpm_sampling(float)
Number of pixel per λ/D in the mask plane. For theclassical_Lyot
focal plane mask, it is an optional parameter, with a default value equal to 20. -
p_corono.set_lyot_fpm_radius(float)
Radius of the mask in λ/D units. Exclusive to theclassical_Lyot
focal plane mask. -
p_corono.set_lyot_stop_name(str)
Lyot stop keyword, or path to a fits file. Only the Lyot stop of SPHERE is coded in Compass. It is accessible with the keywordSPHERE_APLC_Lyot_stop
. Otherwise, you may set your own apodizer with a path to a fits file of size(pupdiam, pupdiam)
.
Optional parameters :
delta_wav, nb_wav
p_corono.set_babinet_trick(bool)
True for enabling Babinet propagation method. Default : False. Forced to True for aclassical_Lyot
focal plane mask.
Example of use :
p_corono0 = conf.Param_corono()
p_coronos = [p_corono0]
p_corono0.set_type('custom') # type of coronograph
p_corono0.set_wavelength_0(1.6) # [μm] wavelength
p_corono0.set_dim_image(200) # [pixel] size of the science image
p_corono0.set_image_sampling(3.5) # [pixel] size of lambda/D in pixel
p_corono0.set_apodizer_name('/home/username/my_apodizer.fits') # your own apodizer
p_corono0.set_focal_plane_mask_name('classical_Lyot') # round mask
p_corono0.set_fpm_radius(2.3) # radius of the mask in lambda/D units
p_corono0.set_lyot_stop_name('SPHERE_APLC_Lyot_stop') # Lyot stop of SPHERE
Non settable parameters
Some parameters are automatically calculated by the simulation, but they are still acessible in the configuration module with the associated getter. For instance, the array of simulated wavelengths is available in supervisor.config.p_coronos[coro_index].get_wav_vec()
.
Other accessible parameters are :
supervisor.config.p_coronos[coro_index].get_apodizer()
Return the apodizer array, of shape(pupdiam, pupdiam)
.supervisor.config.p_coronos[coro_index].get_focal_plane_mask()
Return the focal plane mask array. It is of shape(dim_fpm, dim_fpm, nb_wav)
, with the simulated wavelengths along the third dimension.supervisor.config.p_coronos[coro_index].get_Lyot_stop()
Return the Lyot stop array, of shape(pupdiam, pupdiam)
.
NCPA
Compass already has a function to add NCPA phase screens. It is in the target component :
supervisor.target.set_ncpa_tar(tar_index, ncpa)
Set a NCPA phase screen, in microns. Has to be a 2D array of size(pupdiam, pupdiam)
. The parameter tar_index must be set to 0, as the coronagraph module gets the residual phase from the target 0.
Amplitude aberrations are available in the coronagraph, with the function :
supervisor.corono.set_electric_field_amplitude(coro_index, amplitude)
Set the electric field amplitude before propagation through the coronagraph. The default amplitude is constant and equal to 1. Has to be a 3D array of size(pupdiam, pupdiam, nb_wav)
.
To simulate temporally evolving aberrations, you should update the screens at each iteration.
Known issues and possible improvements
-
Apodizer, focal plane mask and Lyot stop arrays are real and cannot be complex.
-
The wavelength array is defined as nλ wavelengths evenly distributed in $$\left[ \lambda_0 - \frac{\Delta \lambda}{2}, \lambda_0 + \frac{\Delta \lambda}{2}]\right]$$ However, these wavelengths simulate a bandwidth slightly larger than Δλ. It would be a better approximation to set the lower and upper bounds of the wavelength array at $$\lambda_0 - \frac{\Delta \lambda}{2} + \frac{\Delta \lambda}{2 n_{\lambda}}\verb! and ! \lambda_0 + \frac{\Delta \lambda}{2} - \frac{\Delta \lambda}{2 n_{\lambda}} \verb! respectively!.$$
-
Only the residual phase from the target number 0 is send to the coronagraphs. It might be relevant to account for each target, especially if we want to add planets in the field of view.
-
For the SPHERE APLC coronagraph, if the image sampling is not provided, a value is autocomputed to match the IRDIS pixel scale of 12.25 mas. The formula used is $$\verb!image_sampling! = \frac{\lambda_0 / D}{\verb!irdis_pixel_scale!} $$ with $$D = D_{\mathrm{telescope}} = 8 m$$ But the Lyot stop diameter should be used : $$D = D_{\mathrm{Lyot}} \simeq 0.96 D_{\mathrm{telescope}}$$
-
The Lyot stop of SPHERE does not feature the dead actuator patches.