COMPASS  5.4.4
End-to-end AO simulation tool using GPU acceleration
genericCoronagraph.py
1 
37 import numpy as np
38 import shesha.config as conf
39 import shesha.constants as scons
40 from shesha.supervisor.components.targetCompass import TargetCompass
41 from abc import ABC, abstractmethod
42 from shesha.util.coronagraph_utils import compute_contrast
43 
44 class GenericCoronagraph(ABC):
45  """ Generic class for Compass Coronagraph modules
46 
47  Attributes:
48  _spupil: (np.ndarray[ndim=2, dtype=np.float32]): Telescope pupil mask
49 
50  _pupdiam : (int): Number of pixels along the pupil diameter
51 
52  _dim_image :(int): Coronagraphic image dimension
53 
54  _p_corono: (Param_corono): Coronagraph parameters
55 
56  _target: (TargetCompass): Compass Target used as input for the coronagraph
57 
58  _norm_img : (float): Normalization factor for coronagraphic image
59 
60  _norm_psf : (float): Normalization factor for PSF
61 
62  _coronagraph: (SutraCoronagraph): Sutra coronagraph instance
63  """
64  def __init__(self, p_corono: conf.Param_corono, p_geom: conf.Param_geom, targetCompass: TargetCompass):
65  """ Initialize a coronagraph instance with generic attributes
66 
67  Args:
68  p_corono: (Param_corono): Compass coronagraph parameters
69 
70  p_geom: (Param_geom): Compass geometry parameters
71 
72  targetCompass: (TargetCompass): Compass Target used as input for the coronagraph
73  """
74  self._spupil_spupil = p_geom.get_spupil()
75  self._pupdiam_pupdiam = self._spupil_spupil.shape[0]
76  self._dim_image_dim_image = p_corono._dim_image
77  self._p_corono_p_corono = p_corono
78  self._target_target = targetCompass
79  self._norm_img_norm_img = 1
80  self._norm_psf_norm_psf = 1
81 
82  self._coronagraph_coronagraph = None
83 
84  def compute_image(self, *, comp_psf: bool = True, accumulate: bool = True):
85  """ Compute the SE coronagraphic image, and accumulate it in the LE image
86 
87  Args:
88  comp_psf: (bool, optionnal): If True (default), also compute the PSF SE & LE
89  accumulate: (bool, optional): If True (default), the computed SE image is accumulated in
90  long exposure
91  """
92  self._coronagraph_coronagraph.compute_image(accumulate=accumulate)
93  if comp_psf:
94  self.compute_psfcompute_psf(accumulate=accumulate)
95 
96  def compute_psf(self, *, accumulate: bool = True):
97  """ Compute the SE psf, and accumulate it in the LE image
98 
99  Args:
100  accumulate: (bool, optional): If True (default), the computed SE psf is accumulated in
101  long exposure
102  """
103  self._coronagraph_coronagraph.compute_psf(accumulate=accumulate)
104 
105  def get_image(self, *, expo_type:str=scons.ExposureType.LE):
106  """ Return the coronagraphic image
107 
108  Args:
109  expo_type: (str, optional): If "le" (default), returns the long exposure image.
110  If "se", returns short exposure one.
111 
112  Return:
113  img: (np.ndarra[ndim=2,dtype=np.float32]): coronagraphic image
114  """
115  if expo_type == scons.ExposureType.LE:
116  img = np.array(self._coronagraph_coronagraph.d_image_le)
117  if(self._coronagraph_coronagraph.cntImg):
118  img /= self._coronagraph_coronagraph.cntImg
119  if expo_type == scons.ExposureType.SE:
120  img = np.array(self._coronagraph_coronagraph.d_image_se)
121  return img / self._norm_img_norm_img
122 
123  def get_psf(self, *, expo_type:str=scons.ExposureType.LE):
124  """ Return the psf
125 
126  Args:
127  expo_type: (str, optional): If "le" (default), returns the long exposure psf.
128  If "se", returns short exposure one.
129 
130  Return:
131  img: (np.ndarra[ndim=2,dtype=np.float32]): psf
132  """
133  if expo_type == scons.ExposureType.LE:
134  img = np.array(self._coronagraph_coronagraph.d_psf_le)
135  if(self._coronagraph_coronagraph.cntPsf):
136  img /= self._coronagraph_coronagraph.cntPsf
137  if expo_type == scons.ExposureType.SE:
138  img = np.array(self._coronagraph_coronagraph.d_psf_se)
139  return img / self._norm_psf_norm_psf
140 
141  def reset(self):
142  """ Reset long exposure image and PSF
143  """
144  self._coronagraph_coronagraph.reset()
145 
146  def get_contrast(self, *, expo_type=scons.ExposureType.LE, d_min=None, d_max=None, width=None, normalized_by_psf=True):
147  """ Computes average, standard deviation, minimum and maximum of coronagraphic
148  image intensity, over rings at several angular distances from the optical axis.
149 
150  A ring includes the pixels between the following angular distances :
151  d_min + k * width - width / 2 and d_min + k * width + width / 2 (in lambda/D units)
152  with k = 0, 1, 2... until d_min + k * width > d_max (excluded).
153 
154  Args:
155  expo_type: (str, optional): If "le" (default), computes contrast on the long exposure image.
156  If "se", it uses the short exposure one.
157 
158  d_min: (float, optional): Angular radius of the first ring in lambda/D unit.
159  Default = width
160 
161  d_max: (float, optional): Maximum angular distances in lambda/D unit.
162  Default includes the whole image.
163 
164  width: (float, optional): Width of one ring in lambda/D unit.
165  Default = 1 [lambda/D]
166 
167  normalized_by_psf: (bool, optional): If True (default), the coronagraphic image
168  is normalized by the maximum of the PSF
169 
170  Returns:
171  distances: (1D array): angular distances to the optical axis in lambda/D unit
172 
173  mean: (1D array): corresponding average intensities
174 
175  std: (1D array): corresponding standard deviations
176 
177  mini: (1D array): corresponding minimums
178 
179  maxi: (1D array): corresponding maximums
180  """
181  image_sampling = self._p_corono_p_corono._image_sampling
182  if width == None:
183  width = image_sampling
184  else:
185  width = width * image_sampling
186  if d_min == None:
187  d_min = width
188  else:
189  d_min = d_min * image_sampling
190  if d_max == None:
191  d_max = self._dim_image_dim_image / 2 - width / 2
192  else:
193  d_max = d_max * image_sampling
194 
195  center = self._dim_image_dim_image / 2 - (1 / 2)
196  image = self.get_imageget_image(expo_type=expo_type)
197  if normalized_by_psf and np.max(self.get_psfget_psf(expo_type=expo_type)):
198  image = image / np.max(self.get_psfget_psf(expo_type=expo_type))
199 
200  distances, mean, std, mini, maxi = compute_contrast(image, center, d_min, d_max, width)
201  angular_distances = distances / image_sampling
202  return angular_distances, mean, std, mini, maxi
203 
204  def set_electric_field_amplitude(self, amplitude:np.ndarray):
205  """ Set the amplitude of the electric field
206 
207  Args:
208  amplitude: (np.ndarray[ndim=3, dtype=np.float32]): amplitude for each wavelength
209  """
210  self._coronagraph_coronagraph.set_amplitude(amplitude)
def get_psf(self, *str expo_type=scons.ExposureType.LE)
Return the psf.
def get_contrast(self, *expo_type=scons.ExposureType.LE, d_min=None, d_max=None, width=None, normalized_by_psf=True)
Computes average, standard deviation, minimum and maximum of coronagraphic image intensity,...
def compute_psf(self, *bool accumulate=True)
Compute the SE psf, and accumulate it in the LE image.
def __init__(self, conf.Param_corono p_corono, conf.Param_geom p_geom, TargetCompass targetCompass)
def set_electric_field_amplitude(self, np.ndarray amplitude)
Set the amplitude of the electric field.
def get_image(self, *str expo_type=scons.ExposureType.LE)
Return the coronagraphic image.
def compute_image(self, *bool comp_psf=True, bool accumulate=True)
Compute the SE coronagraphic image, and accumulate it in the LE image.
Parameter classes for COMPASS.
Numerical constants for shesha and config enumerations for safe-typing.
Definition: constants.py:1